LogSVC를 구현합시다. EH 메신저 솔루션에 LogSVC 이름의 콘솔 응용 프로젝트를 만드세요. 그리고 이 책에서는 LogSVC를 구현한 이후에 테스트 프로젝트를 만들고 테스트하는 부분은 다루지 않을게요.
LogSVC 프로젝트에 Program.cpp 파일을 추가하여 소스를 구현합시다.
#include "..\\Common\\EHMessenger.h" #pragma comment(lib,"ws2_32") #pragma comment(lib,"..\\Debug\\EHPacketLib") #pragma comment(lib,"..\\Debug\\LogLib") #pragma comment(lib,"..\\Debug\\DbmLib") #pragma comment(lib,"..\\Debug\\EHWrapSocketLib") #include <iostream> using namespace std;
진입점 main 함수에서는 윈속 초기화 후에 로그 서버를 가동하고 윈속을 해제화합니다.
void StartLogServer(); int main() { WSADATA wsadata; WSAStartup(MAKEWORD(2,2),&wsadata); StartLogServer(); WSACleanup(); return 0; } DWORD WINAPI DoIt(LPVOID pin); void StartLogServer() { SOCKET sock = EHWrapSocket::CreateTCPServer(LOG_PORT,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)); } }
로그 서버에서는 로긴 요청과 로그 아웃 요청 메시지를 처리합니다.
void LogInProc(SOCKET sock,EHPacket *ep); void LogOutReqProc(SOCKET sock,EHPacket *ep); DWORD WINAPI DoIt(LPVOID pin) { SOCKET sock = (SOCKET)pin; EHPacket ep(sock); switch(ep.GetMsgId()) { case MID_LOGINREQ: LogInProc(sock,&ep);break; case MID_LOGOUTREQ: LogOutReqProc(sock,&ep); break; } closesocket(sock); return 0; }
로긴 요청 메시지 처리 함수를 작성합시다.
void LogInProc(SOCKET sock,EHPacket *ep) {
수신한 메시지를 로긴 요청 메시지로 변환합니다.
cout<<"로긴 요청 수신"<<endl; LogInReq lr(ep);
Dbm 서비스에 연결하여 아이디 존재 확인 요청 메시지를 전송합니다.
IDExist ie(lr.GetId()); SOCKET clisock = EHWrapSocket::Connect(DBM_IP,DBM_PORT); cout<<"아이디 존재 확인 요청 메시지 전송"<<endl; ie.Serialize(clisock);
Dbm 서비스로부터 응답 메시지를 수신합니다.
EHPacket rep(clisock); closesocket(clisock);
수신한 메시지가 아이디 존재 확인 응답 메시지가 아니면 오류입니다.
if(rep.GetMsgId() != MID_IDEXISTACK) { cout<<"오류!!! 아이디 존재 확인 응답 메시지가 아님"<<endl; return; }
아이디 존재 확인 응답 메시지로 변환합니다.
cout<<"아이디 존재 확인 응답 메시지 수신"<<endl; IDExistAck iea(&rep); int result = LOGIN_RES_OK;
만약 아이디 존재하지 않으면 로긴 결과로 아이디 존재하지 않음을 설정합니다.
if(iea.GetResult() == RES_ID_NOTEXIST) { result = LOGIN_RES_NOTEXIST; cout<<"아이디 존재하지 않음"<<endl; }
아이디가 존재하면 다음 처리를 합니다.
else {
Dbm 서비스에 연결하여 상태 확인 요청 메시지를 전송합니다.
UserSts us(lr.GetId()); clisock = EHWrapSocket::Connect(DBM_IP,DBM_PORT); cout<<"상태 확인 요청 메시지 전송"<<endl; us.Serialize(clisock);
Dbm 서비스로부터 응답 메시지를 수신합니다.
EHPacket rep2(clisock); closesocket(clisock);
만약 수신한 메시지가 상태 확인 응답 메시지가 아니면 오류입니다.
if(rep2.GetMsgId() != MID_USERSTSACK) { cout<<"오류!!! 상태 확인 응답 메시지가 아님"<<endl; return; }
수신한 메시지를 상태 확인 응답 메시지로 변환합니다.
cout<<"상태 확인 응답 메시지 수신"<<endl; UserStsAck usa(&rep2);
만약 결과가 STS_REG가 아니라면 이미 로긴 중이거나 로긴 상태입니다.
if(usa.GetStatus() != STS_REG) { result = LOGIN_RES_LOGGED; cout<<"로긴할 수 없는 상태입니다."<<endl; }
그렇지 않으면 Dbm 서비스에 연결하여 패스워드 일치 확인 메시지를 전송합니다.
else { IsCorrect ic(lr.GetId(),lr.GetPW()); clisock = EHWrapSocket::Connect(DBM_IP,DBM_PORT); cout<<"패스워드 일치 확인 요청 메시지 전송"<<endl; ic.Serialize(clisock);
Dbm 서비스로부터 응답 메시지를 수신합니다.
EHPacket rep3(clisock); closesocket(clisock);
만약 수신한 메시지가 패스워드 일치 확인 요청 응답 메시지가 아니면 오류입니다.
if(rep3.GetMsgId() != MID_ISCORRECTACK) { cout<<"오류!!! 패스워드 일치 확인 요청 응답 메시지가 아님"<<endl; return; }
수신한 메시지를 패스워드 일치 확인 요청 응답 메시지로 변환합니다.
IsCorrectAck ica(&rep3);
일치하지 않으면 결과를 변경합니다.
if(ica.GetResult() == IDPW_NOTCORRECT) { result = LOGIN_RES_NOTCORRECT; } } }
수신한 소켓으로 로긴 요청 결과 메시지를 전송합니다.
LogInRes lres(result); cout<<"로긴 요청 결과 전송"<<endl; lres.Serialize(sock); }
로그 아웃 요청 메시지 처리 함수를 작성합시다.
void LogOutReqProc(SOCKET sock,EHPacket *ep) { cout<<"로그 아웃 요청 수신"<<endl; LogOutReq lr(ep);
로그 아웃 요청 메시지를 수신하면 Log 서비스는 Dbm 서비스에 연결하여 상태 변경 요청 메시지를 전송합니다. 이 때 상태는 로긴 중(STS_LOGGING)을 전달합니다.
ChangeSts cs(lr.GetId(), STS_LOGGING); SOCKET clisock = EHWrapSocket::Connect(DBM_IP,DBM_PORT); cout<<"상태 변경(로긴 중) 요청 메시지 전송"<<endl; cs.Serialize(clisock); closesocket(clisock); }