이번에는 채팅 클라이언트를 구현합시다. 먼저 서버에 약속한 포트 번호와 메시지 크기를 매크로 상수로 정의하고 서버의 IP 주소를 정의합시다. 여러분께서는 자신에 맞게 서버 IP 주소를 변경하세요.
#define PORT_NUM 10200 #define MAX_MSG_LEN 256 #define SERVER_IP "192.168.34.50" //서버 주소 int main() {
먼저 윈속을 초기화합니다.
WSADATA wsadata; WSAStartup(MAKEWORD(2,2),&wsadata);//윈속 초기화
그리고 소켓을 생성합니다.
SOCKET sock; sock = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);//소켓 생성 if(sock == -1) { return -1; }
서버에 연결 요청합니다.
SOCKADDR_IN servaddr={0};//소켓 주소 servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(SERVER_IP); servaddr.sin_port = htons(PORT_NUM); int re = 0; re = connect(sock,(struct sockaddr *)&servaddr,sizeof(servaddr));//연결 요청 if(re == -1) { return -1; }
서버와 연결한 후에는 사용자가 입력한 문자열을 서버에 전송하는 작업과 서버로부터 수신한 정보를 콘솔 화면에 출력하는 작업이 있습니다. 이 두 개의 작업은 서로 독립적으로 수행해야 합니다. 여기에서는 서버로부터 수신한 정보를 콘솔 화면에 출력하는 작업을 별도의 스레드 진입점을 작성하여 처리하기로 합시다.
_beginthread(RecvThreadPoint,0,(void *)sock);
사용자로부터 문자열을 입력받아 전송합니다. 만약 입력한 문자열이 “exit”이면 종료하기로 합시다.
char msg[MAX_MSG_LEN]=""; while(true) { gets_s(msg,MAX_MSG_LEN); send(sock,msg,sizeof(msg),0);//송신 if(strcmp(msg,"exit")==0) { break; } }
소켓을 닫고 윈속을 해제화합니다.
closesocket(sock);//소켓 닫기 WSACleanup();//윈속 해제화 return 0; }
서버로부터 메시지를 수신하여 콘솔 화면에 출력하는 스레드 진입점 함수를 작성합시다.
void RecvThreadPoint(void *param) {
스레드 진입점 인자로 전달받은 소켓을 참조합니다.
SOCKET sock = (SOCKET)param; char msg[MAX_MSG_LEN];
수신한 메시지 길이가 0보다 크면 수신한 정보를 출력하는 것을 반복합니다.
while(recv(sock,msg,MAX_MSG_LEN,0)>0) { printf("%s\n",msg); }
수신한 메시지 길이가 0보다 작거나 같으면 연결이 끊겼거나 오류가 발생한 것이므로 소켓을 닫습니다.
closesocket(sock); }
다음은 이번 실습에서 작성한 채팅 클라이인트 소스 코드입니다.
#include "common.h" #define PORT_NUM 10200 #define MAX_MSG_LEN 256 #define SERVER_IP "192.168.34.50"//서버 IP 주소 void RecvThreadPoint(void *param); int main() { WSADATA wsadata; WSAStartup(MAKEWORD(2,2),&wsadata);//윈속 초기화 SOCKET sock; sock = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);//소켓 생성 if(sock == -1) { return -1; } SOCKADDR_IN servaddr={0};//소켓 주소 servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(SERVER_IP); servaddr.sin_port = htons(PORT_NUM); int re = 0; re = connect(sock,(struct sockaddr *)&servaddr,sizeof(servaddr));//연결 요청 if(re == -1) { return -1; } _beginthread(RecvThreadPoint,0,(void *)sock); char msg[MAX_MSG_LEN]=""; while(true) { gets_s(msg,MAX_MSG_LEN); send(sock,msg,sizeof(msg),0);//송신 if(strcmp(msg,"exit")==0) { break; } } closesocket(sock);//소켓 닫기 WSACleanup();//윈속 해제화 return 0; } void RecvThreadPoint(void *param) { SOCKET sock = (SOCKET)param; char msg[MAX_MSG_LEN]; SOCKADDR_IN cliaddr={0}; int len = sizeof(cliaddr); while(recv(sock,msg,MAX_MSG_LEN,0)>0) { printf("%s\n",msg); } closesocket(sock); }