이번에는 로그 라이브러리가 정상적으로 동작하는지 확인하는 테스트 프로그램을 작성해 봅시다.
먼저 콘솔 응용 프로젝트로 테스트 로그 서버(TracerLogServer)를 추가합니다. 그리고 Program.cpp 소스 파일을 추가하고 필요한 헤더 파일을 포함합니다.
#include "..\\Common\\EHPacket.h" #include "..\\Common\\LogInReq.h" #include "..\\Common\\LogInRes.h" #include "..\\Common\\LogOutReq.h" #include "..\\Common\\ehmsg.h"
윈속 라이브러리와 EH 패킷 라이브러리와 로그 라이브러리를 참조 추가합니다.
#pragma comment(lib,"ws2_32") #pragma comment(lib,"..\\Debug\\EHPacketLib") #pragma comment(lib,"..\\Debug\\LogLib") #include <iostream> using namespace std;
진입점인 main에서는 윈속 초기화와 테스트 서버 가동 및 윈속 해제화를 수행합니다.
void StartTestServer(); int main() { WSADATA wsadata; WSAStartup(MAKEWORD(2,2),&wsadata); StartTestServer(); WSACleanup(); return 0; }
테스트 서버 가동 함수를 작성합시다. 앞에서 설명한 내용들이므로 코드 설명은 생략할게요.
struct in_addr GetDefaultMyAddr(); DWORD WINAPI DoIt(LPVOID pin); void StartTestServer() { SOCKET sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(sock == -1) { printf("소켓 생성 실패!\n"); return; } SOCKADDR_IN servaddr = {0}; servaddr.sin_family = AF_INET;//PF_INET; servaddr.sin_addr = GetDefaultMyAddr(); servaddr.sin_port = htons(10200); int re = 0; re = bind(sock,(SOCKADDR *)&servaddr,sizeof(servaddr)); if(re == -1) { printf("bind 실패\n"); return; } re = listen(sock,5); SOCKADDR_IN clientaddr; int len = sizeof(clientaddr); SOCKET dosock; DWORD ThreadID; while(1) { dosock = accept(sock,(SOCKADDR *)&clientaddr, &len); //클라이언트와 통신할 쓰레드 생성 CloseHandle(CreateThread(0,0,DoIt,(LPVOID)dosock,0,&ThreadID)); } } struct in_addr GetDefaultMyAddr() { char hostname[256]=""; gethostname(hostname,255); hostent *hentry = gethostbyname(hostname); struct in_addr addr={0}; while(hentry && hentry->h_name) { if(hentry->h_addrtype == AF_INET) { memcpy(&addr,hentry->h_addr_list[0],sizeof(addr)); return addr; } hentry++; } return addr; } void LogInReqProc(SOCKET sock,EHPacket *ep); void LogInResProc(SOCKET sock,EHPacket *ep); void LogOutReqProc(SOCKET sock,EHPacket *ep); DWORD WINAPI DoIt(LPVOID pin) { SOCKET dosock = (SOCKET)pin; EHPacket ep(dosock); switch(ep.GetMsgId()) { case MID_LOGINREQ: LogInReqProc(dosock,&ep); break; case MID_LOGINRES: LogInResProc(dosock,&ep); break; case MID_LOGOUTREQ: LogOutReqProc(dosock,&ep); break; } closesocket(dosock); return 0; } void LogInReqProc(SOCKET sock,EHPacket *ep) { LogInReq lr(ep); cout<<"로긴 요청"<<endl; cout<<"아이디:"<<lr.GetId()<<" 비밀번호:"<<lr.GetPW()<<endl; } void LogInResProc(SOCKET sock,EHPacket *ep) { LogInRes lr(ep); cout<<"로긴 요청 응답"<<endl; switch(lr.GetResult()) { case LOGIN_RES_OK: cout<<"로긴 성공"<<endl; break; case LOGIN_RES_NOTEXIST: cout<<"아이디 없음"<<endl; break; case LOGIN_RES_LOGGED: cout<<"이미 로긴 중"<<endl; break; case LOGIN_RES_NOTCORRECT: cout<<"비밀번호 불일치"<<endl; break; } } void LogOutReqProc(SOCKET sock,EHPacket *ep) { LogOutReq lor(ep); cout<<"로그 아웃 요청"<<endl; cout<<"아이디:"<<lor.GetId()<<endl; }
콘솔 응용 프로젝트로 테스트 로그 클라이언트(TracerLogClient)를 추가합니다. Program.cpp 소스 파일을 추가하고 필요한 헤더 파일을 포함합니다. 가입 클라이언트 작성 방법과 같으므로 코드 설명은 생략할게요.
#include "..\\Common\\EHPacket.h" #include "..\\Common\\LogInReq.h" #include "..\\Common\\LogInRes.h" #include "..\\Common\\LogOutReq.h" #include "..\\Common\\ehmsg.h" #pragma comment(lib,"ws2_32") #pragma comment(lib,"..\\Debug\\EHPacketLib") #pragma comment(lib,"..\\Debug\\LogLib") #include <iostream> using namespace std; SOCKET Connect(const char *ip, int port) { SOCKET 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(ip); servaddr.sin_port = htons(port); int re = 0; re = connect(sock,(SOCKADDR *)&servaddr,sizeof(servaddr)); if(re == -1){ return -1; } return sock; }
로긴 요청 메시지를 전송하는 함수를 작성하세요.
void SendLogInReq(string id,string pw) { SOCKET sock; LogInReq lr(id,pw); cout<<"로긴 요청 전송"<<endl; cout<<"아이디:"<<lr.GetId()<<" 비밀번호:"<<lr.GetPW()<<endl; sock = Connect("192.168.34.50",10200); lr.Serialize(sock); closesocket(sock); }
로긴 응답 메시지를 전송하는 함수를 작성하세요.
void SendLogInRes(int result) { SOCKET sock; LogInRes lr(result); cout<<"로긴 요청 응답 전송"<<endl; switch(result) { case LOGIN_RES_OK: cout<<"로긴 성공"<<endl; break; case LOGIN_RES_NOTEXIST: cout<<"아이디 없음"<<endl; break; case LOGIN_RES_LOGGED: cout<<"이미 로긴 중"<<endl; break; case LOGIN_RES_NOTCORRECT: cout<<"비밀번호 불일치"<<endl; break; } sock = Connect("192.168.34.50",10200);//서버 IP 주소를 변경하세요. lr.Serialize(sock); closesocket(sock); }
로그 아웃 요청하는 함수를 작성하세요.
void SendLogOutReq(string id) { SOCKET sock; LogOutReq lor(id); cout<<"로그 아웃 전송"<<endl; cout<<"아이디:"<<lor.GetId()<<endl; sock = Connect("192.168.34.50",10200);//서버 IP 주소를 변경하세요. lor.Serialize(sock); closesocket(sock); }
void StartTestClient() { SendLogInReq("hgd","abc"); SendLogInRes(LOGIN_RES_OK); SendLogInRes(LOGIN_RES_NOTEXIST); SendLogOutReq("hgd"); SendLogInRes(LOGIN_RES_LOGGED); SendLogInRes(LOGIN_RES_NOTCORRECT); SendLogInReq("ehpub","abc"); } int main() { WSADATA wsadata; WSAStartup(MAKEWORD(2,2),&wsadata); StartTestClient(); WSACleanup(); return 0; }