반응형 [ 서버 ] #include <winsock2.h> #include <stdlib.h> #include <stdio.h> #define BUFSIZE 512 // 소켓 함수 오류 출력 후 종료 void err_quit(char *msg) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR); LocalFree(lpMsgBuf); exit(-1); } // 소켓 함수 오류 출력 void err_display(char *msg) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); printf("[%s] %s", msg, (LPCTSTR)lpMsgBuf); LocalFree(lpMsgBuf); } int main(int argc, char* argv[]) { int retval; // 윈속 초기화 WSADATA wsa; if(WSAStartup(MAKEWORD(2,2), &wsa) != 0) return -1; // socket() SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0); if(listen_sock == INVALID_SOCKET) err_quit("socket()"); // bind() SOCKADDR_IN serveraddr; ZeroMemory(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(9000); serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); retval = bind(listen_sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr)); if(retval == SOCKET_ERROR) err_quit("bind()"); // listen() retval = listen(listen_sock, SOMAXCONN); if(retval == SOCKET_ERROR) err_quit("listen()"); // 데이터 통신에 사용할 변수 SOCKET client_sock; SOCKADDR_IN clientaddr; int addrlen; char buf[BUFSIZE+1]; while(1){ // accept() addrlen = sizeof(clientaddr); client_sock = accept(listen_sock, (SOCKADDR *)&clientaddr, &addrlen); if(client_sock == INVALID_SOCKEaccept(listen_socT){ err_display("accept()"); continue; } printf("\n[TCP 서버] 클라이언트 접속: IP 주소=%s, 포트 번호=%d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port)); // 클라이언트와 데이터 통신 while(1){ // 데이터 받기 retval = recv(client_sock, buf, BUFSIZE, 0); if(retval == SOCKET_ERROR){ err_display("recv()"); break; } else if(retval == 0) break; // 받은 데이터 출력 buf[retval] = '\0'; printf("[TCP/%s:%d] %s\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buf); // 데이터 보내기 retval = send(client_sock, buf, retval, 0); if(retval == SOCKET_ERROR){ err_display("send()"); break; } } // closesocket() closesocket(client_sock); printf("[TCP 서버] 클라이언트 종료: IP 주소=%s, 포트 번호=%d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port)); } // closesocket() closesocket(listen_sock); // 윈속 종료 WSACleanup(); return 0; } [ 클라이언트 ] #include <winsock2.h> #include <stdlib.h> #include <stdio.h> #define BUFSIZE 512 // 소켓 함수 오류 출력 후 종료 void err_quit(char *msg) { LPVOID lpMsgBuf; //FORMAT_MESSAGE 에서 나올 메시지 위치를 저장하기 위해 만든 포인터 변수 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| // FORMAT_MESSAGE에 관련된 데이터 버퍼(메모리) 할당 FORMAT_MESSAGE_FROM_SYSTEM, // 시스템으로부터 FORMAT_MESSAGE 를 가져 옴. NULL, WSAGetLastError(), // 가장최근 발생 에러코드 확인. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 언어설정 (메인 언어 / 부 언어[제어판 설정 언어]) (LPTSTR)&lpMsgBuf, // 에러 메시지가 들어가는 위치 0, NULL); MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR); LocalFree(lpMsgBuf); // 메모리에 해제는 별도로. . . exit(-1); } // 소켓 함수 오류 출력 void err_display(char *msg) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); printf("[%s] %s", msg, (LPCTSTR)lpMsgBuf); LocalFree(lpMsgBuf); } // 사용자 정의 데이터 수신 함수 // 데이터 int recvn(SOCKET s, char *buf, int len, int flags) //(소켓 , 버퍼 포인터 , 받을 크기 , 0 ) { int received; // 받은 횟수(량)를 저장하는 변수 char *ptr = buf; // 데이터를 저장할 시작 위치. (데이터를 따로따로 받게되면 데이터 저장위치를 뒤로 변경해야되기때문) int left = len; // 데이터를 받아야할 량. ( 마찬가지로 데이터를 받은 만큼은 - 해서 받아야할 량을 계속 변경 함) // 보낸 데이터를 모두 받을 때까지 리시브 호출. // while(left > 0){ received = recv(s, ptr, left, flags); if(received == SOCKET_ERROR) return SOCKET_ERROR; else if(received == 0) break; left -= received; ptr += received; } return (len - left); // 데이터 전송이 모두 끝나면 데이터 크기 값만큼 리턴 됨. } int main(int argc, char* argv[]) { int retval; // 윈속 초기화 WSADATA wsa; if(WSAStartup(MAKEWORD(2,2), &wsa) != 0) return -1; // socket() :: 소켓 생성 SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == INVALID_SOCKET) err_quit("socket()"); // connect() :: 연결 요청. SOCKADDR_IN serveraddr; ZeroMemory(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(9000); // 서버 포트 번호와 동일하게 serveraddr.sin_addr.s_addr = inet_addr("192.168.1.1"); // 루프백 주소 [자기자신을 의미하는 주소] // inet_addr :: 문자형 주소를 숫자형으로 변경시켜주는 함수 retval = connect(sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr)); // if(retval == SOCKET_ERROR) { err_quit("connect()"); } // 데이터 통신에 사용할 변수 char buf[BUFSIZE+1]; int len; // 서버와 데이터 통신 while(1){ // 데이터 입력 ZeroMemory(buf, sizeof(buf)); printf("\n[보낼 데이터] "); if(fgets(buf, BUFSIZE+1, stdin/*(키보드 버퍼에서 가져옴)*/) == NULL) //gets() 는 엔터키 전까지의 문자열을 가져오지만 fgets 는 모두 가져오기때문에.... break; // '\n' 문자 제거 작업을 해줌. len = strlen(buf); if(buf[len-1] == '\n') buf[len-1] = '\0'; // 입력받은게 엔터키밖에 없다면... if(strlen(buf) == 0) break; // 데이터 보내기 retval = send(sock, buf, strlen(buf), 0); if(retval == SOCKET_ERROR){ err_display("send()"); break; } printf("[TCP 클라이언트] %d바이트를 보냈습니다.\n", retval); // 데이터 받기 retval = recvn(sock, buf, retval, 0); if(retval == SOCKET_ERROR){ err_display("recv()"); break; } else if(retval == 0) break; // 받은 데이터 출력 buf[retval] = '\0'; printf("[TCP 클라이언트] %d바이트를 받았습니다.\n", retval); printf("[받은 데이터] %s\n", buf); } // closesocket() closesocket(sock); // 윈속 종료 WSACleanup(); return 0; } 반응형 공유하기 게시글 관리 Lee's Lab 저작자표시 Share this: 같은 카테고리 글 카테고리 없음 멀티스레드 형식 TCP 서버 2012.09.18 카테고리 없음 멀티스레드(MultiThread) - 2 2012.09.18 카테고리 없음 멀티스레드(MultiThread) 2012.09.17 카테고리 없음 Server / Client 2 2012.09.04