간단한 패킷을 체크하기 위한 클래스
class CTCPConnect
{
public:
class IntPacketSplitter
{
public:
virtual size_t getReadNextSize(const char * p, size_t len) = 0;
};
CTCPConnect()
{
m_socket = INVALID_SOCKET;
}
~CTCPConnect()
{
disconnect();
}
bool connect(const std::string & strServerAddress, int iPort)
{
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(iPort);
{
unsigned long l = inet_addr(strServerAddress.c_str());
if(l == INADDR_NONE)
{
struct hostent * hostinfo;
if((hostinfo = ::gethostbyname(strServerAddress.c_str())) != NULL)
sockAddr.sin_addr = (*(IN_ADDR *)hostinfo->h_addr_list[0]);
}
else sockAddr.sin_addr.s_addr = l;
}
m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( 0 == ::connect(m_socket, (const struct sockaddr *)&sockAddr, sizeof(sockAddr)) )
{
return true;
}
else
{
closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
return false;
}
void disconnect()
{
if ( m_socket != INVALID_SOCKET )
{
closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
}
bool send(const char * p, size_t len)
{
if ( m_socket == INVALID_SOCKET )
{
_ASSERTE(false);
return false;
}
size_t sendByte = 0;
int iRet = 0;
while ( true )
{
iRet = ::send(m_socket, &p[sendByte], (int)(len - sendByte), 0);
if ( iRet <= 0 )
{
_ASSERTE(false);
return false;
}
sendByte += iRet;
if ( sendByte >= len )
{
return true;
}
}
}
bool recvPacket(char * p, size_t len, IntPacketSplitter * packetSplitter)
{
size_t totalRecvSize = 0;
int iRecvSize = 0;
size_t readNextSize = 0;
while ( true )
{
readNextSize = packetSplitter->getReadNextSize(p, totalRecvSize);
if ( readNextSize <= 0 )
{
/// 패킷이 완성되었을 경우이다.
_ASSERTE(totalRecvSize > 0);
return true;
}
iRecvSize = ::recv(m_socket, &p[totalRecvSize], (int)readNextSize, 0);
if ( iRecvSize <= 0 )
{
_ASSERTE(false);
return false;
}
totalRecvSize += iRecvSize;
}
}
enum
{
MAX_PACKET_SIZE = 1024
};
protected:
SOCKET m_socket;
};
class LinePacketSplitter : public CTCPConnect::IntPacketSplitter
{
public:
/// 다음 읽을 바이트를 돌려준다.
virtual size_t getReadNextSize(const char * p, size_t len)
{
if ( len <= 0 ) return 1;
/// 마지막의 바이트가 'end line' 이면 패킷이 완성된 것이다.
if ( p[len-1] == '\n' ) return 0;
return 1;
}
};