DragonNest/Common/NxServerLib/src/NxClientSession.cpp

323 lines
6.8 KiB
C++
Raw Normal View History

2024-12-19 09:48:26 +08:00
#include "stdafx.h"
#include "NxClientSession.h"
NxClientSession::_ClientSessionList
NxClientSession::ms_SessionList;
NxClientSession::NxClientSession()
: m_RecvPacketSize( 0 ), m_Socket( INVALID_SOCKET ), m_SessionEvent( INVALID_HANDLE_VALUE )
{
}
NxClientSession::~NxClientSession()
{
_RemoveClientSession((NxClientSession*)this);
Close();
}
void
NxClientSession::_AddClientSession(NxClientSession* pClientSession)
{
for ( size_t i = 0 ; i < ms_SessionList.size() ; i++ )
{
NxClientSession* pSession = ms_SessionList.at(i);
if ( pSession && pSession == pClientSession )
return;
}
ms_SessionList.push_back(pClientSession);
}
bool
NxClientSession::_RemoveClientSession(NxClientSession* pClientSession)
{
for ( size_t i = 0 ; i < ms_SessionList.size() ; i++ )
{
NxClientSession* pSocket = ms_SessionList.at(i);
if ( pSocket && pSocket == pClientSession )
{
ms_SessionList.erase(ms_SessionList.begin()+i);
return true;
}
}
return false;
}
void
NxClientSession::UpdateClientSession()
{
for ( int i = 0 ; i < (int)ms_SessionList.size() ; i++ )
{
NxClientSession* pClientSession = ms_SessionList.at(i);
if ( pClientSession )
pClientSession->_SelectEvent();
}
}
void
NxClientSession::TraceGetLastError()
{
int nResult = WSAGetLastError();
TCHAR Buf[512] = {NULL};
::FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, nResult, LANG_SYSTEM_DEFAULT, Buf, 512, NULL );
OutputDebugString(Buf);
}
//--------------------------------------------------------------------
bool
NxClientSession::Create(NxClientSessionType nSocketType)
{
int nRet = 0;
m_SocketType = nSocketType;
// Create socket
if ( m_SocketType == NxClientSession::NX_TCP )
{
m_Socket = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
}
else if ( m_SocketType == NxClientSession::NX_UDP )
{
m_Socket = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
}
if( m_Socket == INVALID_SOCKET || nRet == SOCKET_ERROR )
return false;
_AddClientSession((NxClientSession*)this);
m_SessionEvent = ::WSACreateEvent();
return true;
}
bool
NxClientSession::Bind(const TCHAR* szIPAddress, unsigned int nPortNo )
{
int nError;
::memset( &m_SockAddr, 0, sizeof( m_SockAddr ) );
m_SockAddr.sin_family = AF_INET;
m_SockAddr.sin_addr.s_addr = INADDR_ANY;//::inet_addr( INADDR_ANY );
m_SockAddr.sin_port = ::htons( nPortNo );
nError = ::bind( m_Socket, ( const sockaddr* )&m_SockAddr, sizeof( m_SockAddr ) );
::_stprintf_s( m_szIPAddress, _T("%d.%d.%d.%d"),
m_SockAddr.sin_addr.S_un.S_un_b.s_b1,
m_SockAddr.sin_addr.S_un.S_un_b.s_b2,
m_SockAddr.sin_addr.S_un.S_un_b.s_b3,
m_SockAddr.sin_addr.S_un.S_un_b.s_b4 );
return ( nError != SOCKET_ERROR );
}
//--------------------------------------------------------------------
void
NxClientSession::ConnectTo( const TCHAR* szIPAddress, unsigned int nPort )
{
if ( m_SocketType == NX_UDP )
return;
if ( m_Socket == 0 )
{
return;
}
// Initialize sockaddr_in structure
struct sockaddr_in serv_addr;
::ZeroMemory( &serv_addr, sizeof( serv_addr ) );
serv_addr.sin_family = AF_INET;
#ifdef _UNICODE
char szBuff[256]="";
NxWideStringToMultiString(szBuff, szIPAddress );
serv_addr.sin_addr.s_addr = ::inet_addr( szBuff );
#else
serv_addr.sin_addr.s_addr = ::inet_addr( szIPAddress );
#endif
serv_addr.sin_port = ::htons( nPort );
// Try to connect server
if( ::connect( m_Socket, ( struct sockaddr* )&serv_addr, sizeof( serv_addr ) ) != 0 )
OnConnect( ::WSAGetLastError() );
else
OnConnect( 0 );
}
void
NxClientSession::Close()
{
if( m_SessionEvent != INVALID_HANDLE_VALUE )
{
::WSACloseEvent( m_SessionEvent );
m_SessionEvent = INVALID_HANDLE_VALUE;
}
::shutdown( m_Socket, SD_BOTH );
::closesocket( m_Socket );
}
//--------------------------------------------------------------------
int
NxClientSession::Send( NxPacket& packet )
{
DWORD writtenBytes;
DWORD dwFlags = 0;
WSABUF wsaBuf;
wsaBuf.buf = packet.GetPacketBuffer();
wsaBuf.len = packet.GetPacketSize();
int nResult = ::WSASend(m_Socket, &wsaBuf, 1, &writtenBytes, 0, NULL, NULL);
if ( nResult < 0 )
{
NxClientSession::TraceGetLastError();
}
return nResult;
}
int
NxClientSession::SendTo(NxPacket& packet, sockaddr_in* ToAddr)
{
DWORD writtenBytes =0;
DWORD dwFlags = 0;
WSABUF wsaBuf;
wsaBuf.buf = packet.GetPacketBuffer();
wsaBuf.len = packet.GetPacketSize();
int nResult = 0;
nResult = ::WSASendTo( m_Socket, &wsaBuf, 1, &writtenBytes, 0, (sockaddr*)ToAddr, sizeof(sockaddr), NULL, NULL);
if ( nResult < 0 )
{
NxClientSession::TraceGetLastError();
}
return nResult;
}
void
NxClientSession::OnReceive()
{
if ( m_SocketType == NX_TCP )
{
_RecvPacket_TCP();
}
else if ( m_SocketType == NX_UDP )
{
_RecvPacket_UDP();
}
}
void
NxClientSession::_RecvPacket_TCP()
{
// <20><>Ŷ Ǯ<><C7AE><EFBFBD><EFBFBD> <20>Ҵ<EFBFBD> <20>޴´<DEB4>.
NxPacket ReceivedPacket;
DWORD bytesTransferred;
DWORD bufSize = PACKETBUFFERSIZE - m_RecvPacketSize;
DWORD dwFlags = 0;
WSABUF wsaBuf;
wsaBuf.buf = &(m_RecvBuffer[m_RecvPacketSize]);
wsaBuf.len = bufSize;
// Receiving packet
::WSARecv(m_Socket, &wsaBuf, 1, &bytesTransferred, &dwFlags, NULL, NULL);
if( bytesTransferred > 0 )
m_RecvPacketSize += bytesTransferred;
while( m_RecvPacketSize > 0 )
{
ReceivedPacket.CopyToBuffer( m_RecvBuffer, m_RecvPacketSize );
if( ReceivedPacket.IsValidPacket() == true && m_RecvPacketSize >= ( int )ReceivedPacket.GetPacketSize() )
{
// Packet parsing
OnPacket(ReceivedPacket);
char buffer[PACKETBUFFERSIZE] = {0,};
m_RecvPacketSize -= ReceivedPacket.GetPacketSize();
::CopyMemory( buffer, ( m_RecvBuffer + ReceivedPacket.GetPacketSize() ), m_RecvPacketSize );
::CopyMemory( m_RecvBuffer, buffer, m_RecvPacketSize );
}
else
break;
}
}
void
NxClientSession::_RecvPacket_UDP()
{
NxPacket ReceivedPacket;
DWORD bytesTransferred;
DWORD dwFlags = 0;
WSABUF wsaBuf;
wsaBuf.buf = ReceivedPacket.GetPacketBuffer();
wsaBuf.len = PACKETBUFFERSIZE;
sockaddr_in FromAddr;
::ZeroMemory(&FromAddr, sizeof(sockaddr_in));
int FromSize = sizeof(sockaddr_in);
// Receiving packet
int nResult = ::WSARecvFrom( m_Socket, &wsaBuf, 1, &bytesTransferred, &dwFlags,
(sockaddr*)&FromAddr, &FromSize, NULL, NULL);
OnPacket(ReceivedPacket, (sockaddr_in*)&FromAddr);
}
//--------------------------------------------------------------------
void
NxClientSession::_SelectEvent()
{
WSANETWORKEVENTS NetEvent;
// Event select
::ZeroMemory( &NetEvent, sizeof( NetEvent ) );
::WSAEventSelect( m_Socket, m_SessionEvent, FD_READ | FD_CLOSE | FD_CONNECT );
::WSAEnumNetworkEvents( m_Socket, m_SessionEvent, &NetEvent );
if( ( NetEvent.lNetworkEvents & FD_READ ) == FD_READ )
OnReceive();
if( ( NetEvent.lNetworkEvents & FD_CLOSE ) == FD_CLOSE )
OnClose();
if( ( NetEvent.lNetworkEvents & FD_CONNECT ) == FD_CONNECT )
OnConnect( NetEvent.iErrorCode[FD_CONNECT_BIT] );
}