DragonNest/Common/NxServerLib/src/NxClientSession.cpp
2024-12-19 09:48:26 +08:00

322 lines
6.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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] );
}