해결이 되지 않아 다시 올립니다. 헬프미~~~ 스트림
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 ();
답변이 하나두 ;;;;; 없네요..
이렇게 답변이 없을 줄이야.. ^^
다들 수고하세요.
긴 소스는 읽기 귀찮아서......소스 내용은 읽지 않고 소스 위에
긴 소스는 읽기 귀찮아서......
소스 내용은 읽지 않고 소스 위에 있는 글만 있어서 답변 드리자면
recv 가 블럭이냐 논블럭이냐가 결정되는게 아니고
recv 에 넘겨주는 소켓이 블럭이냐 논블럭이냐가 중요합니다.
recv 는 둘 다 작동하죠.
소켓은 기본은 블럭입니다. 이걸 임의로 논블럭으로 셋팅해줘야
논블럭으로 작동합니다.
답변 감사합니다.제가 너무 긴걸 올렸군요.. ^^ 답답해서요..
답변 감사합니다.
제가 너무 긴걸 올렸군요.. ^^ 답답해서요..
더욱더 자세히 알았습니다.
사실 새벽에 해결 봤거든요.... ^^ 삽질의 결과가 갠잔네요. 뿌듯
수고하세요.
댓글 달기