해결이 되지 않아 다시 올립니다. 헬프미~~~ 스트림

hiscom의 이미지

cbycby님, ssehoony님 너무나 감사합니다.
recv등등을 다시 공부하고 있습니다.. ^^&
입출력이 넘 힘드네요..

제가 아는분이 이걸 빨리 맹글어 달라 협박을 해서 공부하는 겸하고 있어요.
그런데 스트레스를 너무 받는군요.. ^^

아래에 지금까지 한 소스를 올립니다. 더좋은 아이디어나 조언좀 부탁드려요.

3가지의 소스입니다.
우선 기능은 집이나 회사에서 유동IP를 사용하는 관계로 가끔 외부에서 접근이 않될 경우를 대비해서

1번째 소스인 프로그램을 유동아이피 하단 컴에 설치해서 일정 시간 마다 센타에 있는 든든한 서버로 전송하면

든든한 서버에 설치된 2번째 소스가 ID와 IP를 저장해 두고 있다가

3번째 소스를 가지고 다니다가 아무곳에서나 서버에 요청하면 회사나 집 등등의 1번째 소스가 들어가 있는 컴의
현재 IP를 알수 있게 하려고 해요. (ㅎㅎ 갠잔은 아이디어죠)

서버로 1분마다 전송되는 첫번째 소스와 그와 관련된 서버용 소스중 일부는 작동이 잘됩니다.
구조체와 파일에 정확히 쌓이죠.

문제는 가지고 다니는 소스(3번째 소스)에서 recv하는 순간 리턴하지 않고 "응답없음" 으로 블러킹 되네요..ㅜㅜ
물론 서버도 블러킹 되고요.

recv함수는 넌 블러킹 함수인 것으로 알고 있는데 이상해요.

로직에 문제가 있는듯한데요.. 정말 못찾겠어요..
믿을 곳이 이곳 밖에 없어서 이렇게 부탁드립니다. ㅜㅜ 다시 수행의 길로 접어드는 군요. ^^ 재미있긴하지만...

// ###########################################################
// 서버로 1분마다 ID를 전송하는 프로그램 (Windows)
			.
			.
			.		
		// 시간 설정
	SetTimer (hwnd, ID_TIMER, 60000, NULL);

	if (WSAStartup (MAKEWORD (2, 2), &WSAData))
	{
		MessageBox (hwnd, TEXT ("WSAStartup() error !"),
					NULL, MB_ICONERROR);
		return TRUE;
	}
		// 소켓 빼옴
	sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (sock == INVALID_SOCKET)
	{
		MessageBox (hwnd, TEXT ("socket() error !"),
					NULL, MB_ICONERROR);
		WSACleanup ();
		return TRUE;
	}
		
		// 구조체 초기화
	memset (&sa, 0, sizeof (sa));
	sa.sin_family			= AF_INET;
	sa.sin_port				= htons (8282);
	sa.sin_addr.S_un.S_addr	= inet_addr (szIPAddr);

		// 서버님 소켓 주세요~~
	connect (sock, (SOCKADDR*) &sa, sizeof (sa));

		// 버퍼 청소
	memset (IDBuffer, 0, sizeof (IDBuffer));

		// 컨트롤에 있는 ID(숫자char*)를 버퍼에 넣는다.
	GetWindowText (GetDlgItem (hwnd, IDC_ID), 
						IDBuffer, sizeof (IDBuffer));

		// ID 전송
	send(sock, IDBuffer, strlen(IDBuffer), 0);

	closesocket (sock);
	WSACleanup ();



// #######################################################
// 서버 프로그램       (Linux)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define PORT		8282
#define ID_MAX		3
#define IP_MAX		16
#define MAX	256

#pragma pack(1)
typedef struct __str_data {
				char id[ID_MAX];
				char ip[IP_MAX];
} _str_data ;
#pragma pack()

_str_data str_data[MAX];

void error_handling (char* message);

int main(void)
{
	int serv_sock;
	int clnt_sock;
	struct sockaddr_in serv_addr;
	struct sockaddr_in clnt_addr;
	int clnt_addr_size;
	char id_temp[ID_MAX];
	char ip_temp[IP_MAX];
	int str_len;
	int max_num = 0;
	int id_num;
	int i;
	FILE * file;
	int byte = 0;
	char buffer[1024];

// socket에서 listen까지 ================================
	serv_sock = socket(PF_INET, SOCK_STREAM, 0);
	if(serv_sock == -1)
		error_handling("socket() error");

	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(PORT);

	if( bind(serv_sock, (struct sockaddr*)&serv_addr, 
							sizeof(serv_addr)) == -1)
		error_handling("bind() error");

	if( listen(serv_sock, MAX) == -1)
		error_handling("listen() error");
// =======================================================

	while(1){

		memset(id_temp, 0, sizeof(id_temp));
		memset(ip_temp, 0, sizeof(ip_temp));
		clnt_addr_size = sizeof(clnt_addr);

			// 연결수락후 클라이언트 소켓을 얻는다.
		clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

			// 클라이언트의 접속이 이루어지면
        	strcpy(ip_temp,  inet_ntoa(clnt_addr.sin_addr));		// IP와 
		while( (read(clnt_sock, id_temp, sizeof(id_temp))) != 0);	// ID를 임시 저장한다.

			// 숫자로 변경해서 저장될 버퍼의 인덱스로 사용
		id_num = atoi(id_temp);

			// 구조체 배열에 넣는다.
		strcpy(str_data[id_num].id, id_temp);
		str_data[id_num].id[ID_MAX-1] = '\0';
		strcpy(str_data[id_num].ip, ip_temp);
		str_data[id_num].ip[IP_MAX-1] = '\0';

           // 배열내 ID의 최대값을 얻는다.
        if(max_num < id_num)
                max_num = id_num;

			// 쓰기 전용 파일 개방 및 저장
		file = fopen("DATA.DAT", "wb");
		if(file == NULL)
			error_handling("file open error!\n");

		for(i=0 ; i < max_num+1 ; i++)
			fprintf(file, "%s %s  ", str_data[i].id, str_data[i].ip);

		if(fclose(file) != 0)
			error_handling("file close error!\n");

			// ID가 0이면 파일을 전송한다.
			// 일기전용으로 파일 개방 및 전송
		if ( !strcmp(id_temp, "0"))
		{
			printf("\n 읽기 전용으로 파일을 연다.");
			file = fopen("DATA.DAT", "rt");
			if(file == NULL)
				error_handling("file open error!\n");

			byte = 0;	// 파일 바이트수 초기화
			i=0;

				//파일을 열어서 버퍼로 저장한다.
			while(feof(file) == 0)
			{
				buffer[i++] = fgetc(file);
				if(ferror(file)!=0)
					error_handling("fgetc() error!");	
				byte++;
			}
			buffer[byte-1] = '\0';

				//전송 시작...
			write(clnt_sock, buffer, byte-1);
		}
				// 소켓을 닫는다.
			close(clnt_sock);

	} // while(1) 끝....
	return 0;
}

void error_handling(char* message)
	{
		fputs(message, stderr);
		fputc('\n', stderr);
		exit(1);
	}



// ################################################################
// 서버에서 저장된 목록을 수신하기위한 프로그램  (Windows)
#include <windows.h>
#include <stdio.h>

#define BUFSIZE		1024
		.
		.
		.

	static char		szIPAddr [32] = {"220.231.165.54"};
	static HWND		hwndButton, hwndEdit;
	static SOCKET	sock;
	static struct	sockaddr_in sa;
	WSADATA			WSAData;
	char			Buffer[BUFSIZE];

	// 준비 작업 ================================================
			if (WSAStartup (MAKEWORD (2, 2), &WSAData)){
				MessageBox (hwnd, TEXT ("WSAStartup() error !"),
							NULL, MB_ICONERROR);
				return TRUE;
			}

			sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

			if (sock == INVALID_SOCKET){
				MessageBox (hwnd, TEXT ("socket() error !"),
							NULL, MB_ICONERROR);
				WSACleanup ();
				return TRUE;
			}

			memset (&sa, 0, sizeof (sa));
			sa.sin_family			= AF_INET;
			sa.sin_port				= htons (8282);
			sa.sin_addr.S_un.S_addr	= inet_addr (szIPAddr);

	// ==========================================================

				// 서버에 접속을 시도한다.
			connect (sock, (SOCKADDR*) &sa, sizeof (sa));

				// 서버로 "0"을 보내서 저장된 데이터를
				// 보내주도록 한다.
			send(sock, "0", strlen("0"), 0);

				// 버퍼로 수신한다.
			while (recv(sock, Buffer, BUFSIZE-1, 0) != 0);

			// 버퍼에 저장된 목록를 파일로 저장하고
			// 적당히 화면에 뿌리는 작업.....(작업중)

			closesocket (sock);
			WSACleanup ();
hiscom의 이미지

이렇게 답변이 없을 줄이야.. ^^

다들 수고하세요.

ssehoony의 이미지

긴 소스는 읽기 귀찮아서......
소스 내용은 읽지 않고 소스 위에 있는 글만 있어서 답변 드리자면
recv 가 블럭이냐 논블럭이냐가 결정되는게 아니고
recv 에 넘겨주는 소켓이 블럭이냐 논블럭이냐가 중요합니다.
recv 는 둘 다 작동하죠.
소켓은 기본은 블럭입니다. 이걸 임의로 논블럭으로 셋팅해줘야
논블럭으로 작동합니다.

hiscom의 이미지

답변 감사합니다.
제가 너무 긴걸 올렸군요.. ^^ 답답해서요..

더욱더 자세히 알았습니다.

사실 새벽에 해결 봤거든요.... ^^ 삽질의 결과가 갠잔네요. 뿌듯

수고하세요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.