7.4.5 EH 메신저 로그 라이브러리 설계 및 구현 [TCP/IP 소켓 프로그래밍 with 윈도우즈]

이번에는 로그 라이브러리를 설계 및 구현합시다.

로그 라이브러리에는 로긴 요청과 로그 아웃 요청 메시지 처리에 필요한 형식과 기능을 구현할 것입니다. 로그 라이브러리와 관련있는 노드는 클라이언트와 로그 서버입니다.

클라이언트의 Peer 프로그램과 로그 서버의 LogSVC는 로그 라이브러리와 EHPacket 라이브러리를 사용합니다. 그리고 로그 라이브러리도 EHPacket 라이브러리를 사용합니다.

[그림 7.16] 로그 관련 노드 컴포넌트 다이어그램

 이제 로그 라이브러리를 작성합시다. 로그 라이브러리는 LogLib 이름으로 만들게요. 로그 라이브러리에는 로긴 요청하는 LogInReq 클래스와 로긴 요청 응답하는 LogInReponse 클래스, 로그 아웃 요청하는 LogOutReq클래스로 구성할게요.

먼저 EH 메신저 솔루션에 LogLib 이름으로 Win2 프로젝트를 추가하고 DLL 형태로 만드세요.

작성 원리는 가입 라이브러리 작성 원리와 같습니다.

로그 라이브러리에서 공통으로 포함해서 사용할 Log.h 파일을 Common 프로젝트에 추가합니다.

#pragma once

EHPacketLib를 사용해야 하므로 EHPacket.h 파일을 포함하고 EHPacketLib 파일을 참조 추가합니다.

#include "..\\common\\EHPacket.h"
#pragma comment(lib,"..\\Debug\\EHPacketLib")

로그 라이브러리 내부와 사용할 곳에 맞게 __declspec 표현을 할 수 있게 매크로 LOG_DLL를 정의합니다.

#ifdef LOG038IUPHDFJKDIFEWFKDSIFHWELKJFHOISUDFHK
#define LOG_DLL  __declspec(dllexport)
#else
#define LOG_DLL  __declspec(dllimport)
#endif

로긴 요청에 관한 클래스를 정의할 LogInReq.h 파일을 Common 프로젝트에 추가합니다. 작성 방법은 가입 요청에 관한 RegReq.h 파일 같은 방법이므로 작성합니다. 코드 설명은 생략할게요.

#pragma once
#include "Log.h"
#pragma warning(disable:4251)
#include <string>
using namespace std;

class LOG_DLL LogInReq
{
    string id;
    string pw;
public:
    LogInReq(string id,string pw);
    LogInReq(EHPacket *ep);
    string GetId()const;
    string GetName()const;
    void Serialize(SOCKET sock);
};

로그 라이브러리에 LogInReq.cpp 소스 파일을 추가하여 구현합시다. 작성 방법은 RegReq.cpp 파일과 같으므로 코드 설명은 생략할게요.

#define LOG038IUPHDFJKDIFEWFKDSIFHWELKJFHOISUDFHK
#include "..\\common\\LogInReq.h"
#include "..\\Common\\ehmsg.h"

LogInReq::LogInReq(string id,string pw)
{
    this->id = id;
    this->pw = pw;
}
LogInReq::LogInReq(EHPacket *ep)
{
    int idlen = 0;	
    char id[256]="";
    ep->DePacketize(&idlen,sizeof(idlen));
    ep->DePacketize(id,idlen);
    int pwlen=0;
    char pw[256]="";
    ep->DePacketize(&pwlen,sizeof(pwlen));
    ep->DePacketize(pw,pwlen);
    this->id = id;
    this->pw = pw;
}
string LogInReq::GetId()const
{
    return id;
}
string LogInReq::GetPW()const
{
    return pw;
}
void LogInReq::Serialize(SOCKET sock)
{
    EHPacket ep(MID_LOGINREQ);
    int idlen = id.length() + 1;
    ep.Packetize(&idlen,sizeof(idlen));
    ep.Packetize((void *)id.c_str(),idlen);
    int pwlen = pw.length()+1;
    ep.Packetize(&pwlen,sizeof(pwlen));
    ep.Packetize((void *)pw.c_str(),pwlen);
    ep.Serialize(sock);
}

Common 프로젝트에 LogInRes.h 파일을 추가하고 LogInRes 클래스를 정의합시다.

#pragma once
#include "Log.h"

로긴 요청의 응답은 성공과 실패( ID 없음, 이미 로긴 중, ID와 PW 불일치)에 필요한 매크로 상수를 정의합시다.

#define LOGIN_RES_OK          0
#define LOGIN_RES_NOEXIST     1
#define LOGIN_RES_LOGGED      2
#define LOGIN_RES_NOTCORRECT  3

로긴 요청의 응답 클래스인 LogInRes를 정의합니다.

class LOG_DLL LogInRes
{
    int result;
public:
    LogInRes(int result);
    LogInRes(EHPacket *ep);
    int GetResult()const;
    void Serialize(SOCKET sock);
};

로그 라이브러리에 LogInRes.cpp 파일을 추가하여 코드를 작성합시다.

#define LOG038IUPHDFJKDIFEWFKDSIFHWELKJFHOISUDFHK
#include "..\\common\\LogInRes.h"
#include "..\\Common\\ehmsg.h"
LogInRes::LogInRes(int result)
{
    this->result = result;
}
LogInRes::LogInRes(EHPacket *ep)
{
    ep->DePacketize(&result,sizeof(result));
}
int LogInRes::GetResult()const
{
    return result;
}
void LogInRes::Serialize(SOCKET sock)
{
    EHPacket ep(MID_LOGINRES);
    ep.Packetize(&result,sizeof(result)); 
    ep.Serialize(sock);
}

Common 프로젝트에 LogOutReq.h 파일을 추가하고 LogOutReq 클래스를 정의합시다.

#pragma once
#include "Log.h"
#pragma warning(disable:4251)
#include <string>
using namespace std;
class LOG_DLL LogOutReq
{
    string id;
public:
    LogOutReq(string id);
    LogOutReq(EHPacket *ep);
    string GetId()const;
    void Serialize(SOCKET sock);
};

로그 라이브러리에 LogOutReq.cpp 파일을 추가하여 소스를 구현합시다.

#define LOG038IUPHDFJKDIFEWFKDSIFHWELKJFHOISUDFHK
#include "..\\common\\LogOutReq.h"
#include "..\\Common\\ehmsg.h"
LogOutReq::LogOutReq(string id)
{
    this->id = id;
}
LogOutReq::LogOutReq(EHPacket *ep)
{
    int idlen = 0;	
    char id[256]="";
    ep->DePacketize(&idlen,sizeof(idlen));
    ep->DePacketize(id,idlen);
    this->id = id;
}
string LogOutReq::GetId()const
{
    return id;
}
void LogOutReq::Serialize(SOCKET sock)
{
    EHPacket ep(MID_LOGOUTREQ);
    int idlen = id.length() + 1;
    ep.Packetize(&idlen,sizeof(idlen));
    ep.Packetize((void *)id.c_str(),idlen);
    ep.Serialize(sock);
}