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

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

상태 라이브러리에는 상태를 유지하기 위해 주기적으로 보내는 KeepAlive와 다른 계정의 정보를 전송 및 수신하는 OtherUserInfo를 정의할 것입니다. 상태 라이브러리는 클라이언트와 상태 서버에서 사용합니다.

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

[그림 7.17] 상태 관련 노드 컴포넌트 다이어그램

 이제 상태 라이브러리를 작성합시다. 상태 라이브러리는 StsLib 이름으로 만들게요. 상태 라이브러리에는 상태를 유지하기 위해 주기적으로 보내는 KeepAlive 클래스와 다른 계정의 정보에 관한 OtherUserInfo 클래스로 구성할게요.

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

작성 원리는 로그 라이브러리 작성 원리와 같습니다.

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

#pragma once

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

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

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

#ifdef STS038IUPHDFJKDIFEWFKDSIFHWELKJFHOISUDFHK
#define STS_DLL  __declspec(dllexport)
#else
#define STS_DLL  __declspec(dllimport)
#endif

상태 유지를 위해 주기적으로 보내는 KeepAlive에 관한 클래스를 정의할 KeepAlive.h 파일을 Common 프로젝트에 추가합니다. 작성 방법은 LogInReq.h 파일 같은 방법이므로 작성합니다. 코드 설명은 생략할게요.

#pragma once
#include "Sts.h"
#pragma warning(disable:4251)
#include <string>
using namespace std;
class STS_DLL KeepAlive
{
    string id;
    IN_ADDR ip;
    int stsport;
    int smsgport;
    int fileport;
public:
    KeepAlive(string id,IN_ADDR ip,int stsport=0,int smsgport=0,int fileport=0);
    KeepAlive(EHPacket *ep);
    string GetId()const;
    IN_ADDR GetIP()const;
    int GetStsPort()const;
    int GetSmsgPort()const;
    int GetFilePort()const;
    void Serialize(SOCKET sock);
};

StsLib 프로젝트에 KeepAlive.cpp 파일을 추가하고 구현합시다. 구현 방법은 이전과 같으므로 코드 설명은 생략할게요.

#define STS038IUPHDFJKDIFEWFKDSIFHWELKJFHOISUDFHK
#include "..\\common\\KeepAlive.h"
#include "..\\Common\\ehmsg.h"
KeepAlive::KeepAlive(string id,IN_ADDR ip,int stsport,int smsgport,int fileport)
{
    this->id = id;
    this->ip = ip;
    this->stsport = stsport;
    this->smsgport = smsgport;
    this->fileport = fileport;
}
KeepAlive::KeepAlive(EHPacket *ep)
{
    int idlen = 0;
    char id[256]="";
    ep->DePacketize(&idlen,sizeof(idlen));
    ep->DePacketize(id,idlen);
    ep->DePacketize(&ip,sizeof(ip));
    ep->DePacketize(&stsport,sizeof(stsport));
    ep->DePacketize(&smsgport,sizeof(smsgport));
    ep->DePacketize(&fileport,sizeof(fileport));
    this->id = id;
}
string KeepAlive::GetId()const
{
    return id;   
}
IN_ADDR KeepAlive::GetIP()const
{
    return ip;   
}
int KeepAlive::GetStsPort()const
{
    return stsport;    
}
int KeepAlive::GetSmsgPort()const
{
    return smsgport;   
}
int KeepAlive::GetFilePort()const
{
    return fileport;   
}
void KeepAlive::Serialize(SOCKET sock)
{
    EHPacket ep(MID_KEEPALIVE);
    int idlen = id.length() + 1;
    ep.Packetize(&idlen,sizeof(idlen));
    ep.Packetize((void *)id.c_str(),idlen);
    ep.Packetize(&ip,sizeof(ip));
    ep.Packetize(&stsport,sizeof(stsport));
    ep.Packetize(&smsgport,sizeof(smsgport));
    ep.Packetize(&fileport,sizeof(fileport));
    ep.Serialize(sock);
}

이번에는 Common 프로젝트에 OtherUserInfo.h 파일을 추가하고 StsLib 프로젝트에 OtherUserInfo.cpp 파일을 추가하고 구현하세요. 앞에서 계속 만들었던 방법과 같습니다. 코드 설명은 생략할게요.

//OtherUserInfo.h 
#pragma once
#include "Sts.h"
#pragma warning(disable:4251)
#include <string>
using namespace std;
class STS_DLL OtherUserInfo
{
    string id;
    IN_ADDR ip;
    int smsgport;
    int fileport;
public:
    OtherUserInfo(string id,IN_ADDR ip,int smsgport=0,int fileport=0);
    OtherUserInfo(EHPacket *ep);
    string GetId()const;
    IN_ADDR GetIP()const;
    int GetSmsgPort()const;
    int GetFilePort()const;
    void Serialize(SOCKET sock);
};
//OtherUserInfo.cpp 
#define STS038IUPHDFJKDIFEWFKDSIFHWELKJFHOISUDFHK
#include "..\\common\\OtherUserInfo.h"
#include "..\\Common\\ehmsg.h"
OtherUserInfo::OtherUserInfo(string id,IN_ADDR ip,int smsgport,int fileport)
{
    this->id = id;
    this->ip = ip;
    this->smsgport = smsgport;
    this->fileport = fileport;
}
OtherUserInfo::OtherUserInfo(EHPacket *ep)
{
    int idlen = 0;
    char id[256]="";
    ep->DePacketize(&idlen,sizeof(idlen));
    ep->DePacketize(id,idlen);
    ep->DePacketize(&ip,sizeof(ip));
    ep->DePacketize(&smsgport,sizeof(smsgport));
    ep->DePacketize(&fileport,sizeof(fileport));
    this->id = id;
}
string OtherUserInfo::GetId()const
{
	return id;   
}
IN_ADDR OtherUserInfo::GetIP()const
{
    return ip;   
}
int OtherUserInfo::GetSmsgPort()const
{
    return smsgport;   
}
int OtherUserInfo::GetFilePort()const
{
    return fileport;   
}
void OtherUserInfo::Serialize(SOCKET sock)
{
   EHPacket ep(MID_USERINFO);
    int idlen = id.length() + 1;
    ep.Packetize(&idlen,sizeof(idlen));
    ep.Packetize((void *)id.c_str(),idlen);
    ep.Packetize(&ip,sizeof(ip));
    ep.Packetize(&smsgport,sizeof(smsgport));
    ep.Packetize(&fileport,sizeof(fileport));
    ep.Serialize(sock);
}