Files
Client/Server/NFAuthTool/NFAuthServer/NaveServer/NFConnection.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

835 lines
20 KiB
C++

#include "Global.h"
#include "NFConnection.h"
#include <Nave/NFLog.h>
namespace NaveServer {
NFConnection::NFConnection() : m_nMaxBuf(0), m_nMaxPacketSize(0), m_sckListener(NULL),
m_Socket(NULL), m_eConnectFlag(CONNECT_NONE), m_bIsConnect(FALSE),
m_bForce(FALSE), m_hIOCP(NULL), m_pPacketPool(NULL), m_uRecvTickCnt(0)
{
m_RecvPacket.Init();
m_RecvIO.NewIOBuf(0); // 0으로 하면 기본적으로 1024*64만큼 잡힌다.
}
NFConnection::~NFConnection()
{
m_nMaxBuf = m_nMaxPacketSize = 0;
m_sckListener = NULL;
Disconnect();
m_eConnectFlag = CONNECT_NONE;
m_bIsConnect = FALSE;
m_bForce = FALSE;
m_hIOCP = NULL;
m_pPacketPool = NULL;
m_uRecvTickCnt = 0;
m_RecvIO.DeleteIOBuf();
}
BOOL NFConnection::Create( DWORD dwIndex,
HANDLE hIOCP,
SOCKET listener,
NFPacketPool* pPacketPool,
INT nMaxBuf)
{
// 객체의 멤버 변수 설정
m_dwIndex = dwIndex;
m_hIOCP = hIOCP;
m_sckListener = listener;
m_pPacketPool = pPacketPool;
m_nMaxBuf = m_nMaxPacketSize = nMaxBuf;
// 객체 OPEN
if(!Open())
{
// 실패하면 어떻게 해야 하는가? 이 컨넥션 클래스는 죽은 클래스가 된다.
Close_Open(FALSE);
return FALSE;
}
return TRUE;
}
BOOL NFConnection::Open()
{
// 절대 값 있어야 함.
assert(m_nMaxBuf);
assert(m_nMaxPacketSize);
// 패킷 Pool이 제대로 설정 되었는지 검사
if( !m_pPacketPool ) return FALSE;
// Listener Socket 상태 검사
if( m_sckListener == NULL ) return FALSE;
m_RecvIO.InitIOBuf(); // 패킷버퍼를 초기화한다.
// create socket for send/recv
m_Socket = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED );
// 현재 소켓이 제대로 생성 되었는지 검사
if(m_Socket == NULL) return FALSE;
// Accpet할 오버랩구조체와 패킷버퍼를 준비한다.
LPOVERLAPPEDPLUS newolp = PrepareAcptPacket();
if(NULL == newolp)
{
closesocket(m_Socket);
m_Socket = NULL;
return FALSE;
}
/////////////////////////////////////////////////////////////////////
// Socket과 Listener와 연결
// Overlapped에 들어가는 변수가 나중에 IOCP 이벤트 발생 처리에 쓰인다
BOOL bRet = AcceptEx(newolp->sckListen, // Listen Socket
newolp->sckClient, // Socket
&(newolp->wbuf.buf[0]), // 버퍼 포인터
m_nMaxBuf, // 버퍼 사이즈
sizeof(sockaddr_in) + 16, // 소켓 정보 - IP, Address, Name.. etc
sizeof(sockaddr_in) + 16, // 소켓 정보 - IP, Address, Name.. etc
&newolp->dwBytes, // 처리 바이트 크기
&newolp->overlapped); // *중요*
// 에러 처리
if(!bRet && WSAGetLastError() != WSA_IO_PENDING)
{
ShowMessage(ACCEPT_FAILED);
closesocket(m_Socket);
m_Socket = NULL;
ReleaseAcptPacket(newolp);
return FALSE;
}
/////////////////////////////////
// 소켓의 성능 최적화를 위한 세팅
INT zero = 0;
INT err = 0;
// Send Buffer에 대한 세팅
if( (err = setsockopt( m_Socket, SOL_SOCKET, SO_SNDBUF, (CHAR *)&zero, sizeof(zero))) == SOCKET_ERROR)
{
ShowMessage(ACCEPT_FAILED);
closesocket(m_Socket);
m_Socket = NULL;
ReleaseAcptPacket(newolp);
return FALSE;
}
// Receive Buffer에 대한 세팅
if((err = setsockopt( m_Socket, SOL_SOCKET, SO_RCVBUF, (CHAR *)&zero, sizeof(zero) )) == SOCKET_ERROR)
{
ShowMessage(ACCEPT_FAILED);
closesocket(m_Socket);
m_Socket = NULL;
ReleaseAcptPacket(newolp);
return FALSE;
}
// 변수 초기화
InterlockedExchange((LONG*)&m_bIsConnect,0);
Clear();
m_uRecvTickCnt = 0 ;
return TRUE;
}
BOOL NFConnection::Close_Open( BOOL bForce )
{
// 소켓과 리스너 상태 확인
// Disconnect 함수안에서 OnDisconnect(), Clear() 이 호출된다.
Disconnect(bForce);
// 이 패킷 다시 초기화
if(!Open())
{
// 실패하면 어떻게 해야 하는가? 이 컨넥션 클래스는 죽은 클래스가 된다.
// 뭔가 죽은 상태를 표시해주고 체크하자. 그리고 나중에 타이머에서 다시 초기화 해본다.
ShowMessage(DEAD_CONNECTION);
Disconnect();
return FALSE;
}
return TRUE; // 정상 처리
}
VOID NFConnection::ShowMessage(INT MsgIndex)
{
switch(MsgIndex)
{
case ACCEPT_FAILED:
LOG_ERROR((L"[%04d] AcceptEx(): SOCKET_ERROR, %d.", GetIndex(), WSAGetLastError()));
break;
case CLOSE_SOCKET:
LOG_INFO((L"[%04d] 접속 해제.", GetIndex()));
break;
case DEAD_CONNECTION:
LOG_ERROR((L"[%04d] Dead Connection.", GetIndex()));
break;
case CONNECT_SUCCESS:
LOG_INFO((L"[%04d] 접속 성공.", GetIndex()));
break;
case CONNECT_FAILED:
LOG_ERROR((L"[%04d] 접속 실패 (Check Sum 오류).", GetIndex()));
break;
case DISPATCH_FAILED:
LOG_ERROR((L"[%04d] Dispatch return FALSE.", GetIndex()));
break;
case DOIOSWITCH_FAILED:
LOG_ERROR((L"[%04d] DoIo(..) - Switch Default.", GetIndex()));
break;
case ALLOCACPT_FAILED:
LOG_ERROR((L"[%04d] PrepareAcptPacket() acpt packet alloc failed.", GetIndex()));
break;
case PREPAREACPT_FAILED:
LOG_ERROR((L"[%04d] PrepareAcptPacket().newolp == NULL.", GetIndex()));
break;
case PREPARERECVSIZE_FAILED:
LOG_ERROR((L"[%04d] PrepareRecvPacket() srclen > m_nMaxPacketSize.", GetIndex()));
break;
case PREPARESENDSIZE_FAILED:
LOG_ERROR((L"[%04d] PrepareSendPacket() srclen > m_nMaxPacketSize.", GetIndex()));
break;
case ALLOCRECV_FAILED:
LOG_ERROR((L"[%04d] PrepareRecvPacket() recv packet alloc failed.", GetIndex()));
break;
case ALLOCSEND_FAILED:
LOG_ERROR((L"[%04d] PrepareSendPacket() send packet alloc failed.", GetIndex()));
break;
case PREPARERECV_FAILED:
LOG_ERROR((L"[%04d] PrepareRecvPacket().newolp == NULL.", GetIndex()));
break;
case PREPARESEND_FAILED:
LOG_ERROR((L"[%04d] PrepareSendPacket().newolp == NULL.", GetIndex()));
break;
case RELEASEACPT_FAILED:
LOG_ERROR((L"[%04d] ReleaseAcptPacket() free acpt packet failed.", GetIndex()));
break;
case RELEASERECV_FAILED:
LOG_ERROR((L"[%04d] ReleaseRecvPacket() free recv packet failed.", GetIndex()));
break;
case RELEASESEND_FAILED:
LOG_ERROR((L"[%04d] ReleaseSendPacket() free send packet failed.", GetIndex()));
break;
case BINDIOCP_FAILED:
LOG_ERROR((L"[%04d] BindIOCP().lpOverlapPlus == NULL.", GetIndex()));
break;
case RECVPOST_FAILED:
LOG_ERROR((L"[%04d] RecvPost() m_Socket == NULL or IsConnect() == FALSE.", GetIndex()));
break;
case RECVPOSTPENDING_FAILED:
LOG_ERROR((L"[%04d] RecvPost().WSARecv() == SOCKET_ERROR, %d.", GetIndex(), WSAGetLastError()));
break;
// case ALLOCPROC_FAILED:
// LOG_ERROR((L"[%04d] SendPost().AllocProcBuffer == NULL or SOCKET_ERROR, %d.", GetIndex(), WSAGetLastError()));
// break;
case SENDPOSTPENDING_FAILED:
LOG_ERROR((L"[%04d] SendPost().WSASend() == SOCKET_ERROR, %d.", GetIndex(), WSAGetLastError()));
break;
case SENDPOST_FAILED:
LOG_ERROR((L"[%04d] SendPost() == SOCKET_ERROR, %d.", GetIndex(), WSAGetLastError()));
break;
}
}
BOOL NFConnection::DoIo( LPOVERLAPPEDPLUS lpOverlapPlus )
{
// 할당 패킷의 상태 확인
switch(lpOverlapPlus->nConnState)
{
// ACCEPT관련 처리
case ClientIoAccept:
BindIOCP(lpOverlapPlus); // 현재 소켓과 IOCP 바인딩 처리
InterlockedIncrement((LONG*)&m_bIsConnect); // 접속 상태 변수 ON !!!
// 검사된 연결자 아난 경우 연결 해제
if(lpOverlapPlus->dwBytes && strncmp(lpOverlapPlus->wbuf.buf,CONNECT_CHECK_DATA,CONNECT_CHECK_SIZE) == 0)
{
ShowMessage(CONNECT_SUCCESS);
SetConnectFlag(CONNECT_TRUE);
}
else
{
ShowMessage(CONNECT_FAILED);
LOG_ERROR((L"[%04d] Check Sum : %d, %s.", GetIndex(), lpOverlapPlus->dwBytes, lpOverlapPlus->wbuf.buf));
SetConnectFlag(CONNECT_FALSE);
ReleaseAcptPacket( lpOverlapPlus );
break;
}
// Accept 할당 패킷 해제
if(!RecvPost())
{
SetClose_Open(lpOverlapPlus);
break;
}
// TICK 카운트 설정
InterlockedExchange((LONG*)&m_uRecvTickCnt,timeGetTime());
ReleaseAcptPacket( lpOverlapPlus );
break;
// RECEIVE 관련 처리
case ClientIoRead:
// TICK 카운트 설정
InterlockedExchange((LONG*)&m_uRecvTickCnt,timeGetTime());
// 처리 데이타가 없다면
if(lpOverlapPlus->dwBytes == 0)
{
SetClose_Open(lpOverlapPlus, FALSE); // 에러, 객체 다시 초기화
}
else if((INT)lpOverlapPlus->dwBytes == SOCKET_ERROR) // 에러라면
{
SetClose_Open(lpOverlapPlus, TRUE); // 에러, 객체 다시 초기화
}
else// 정상이라면
{
// 메세지 저장
if(!DispatchPacket(lpOverlapPlus))
{
ShowMessage(DISPATCH_FAILED);
SetClose_Open( lpOverlapPlus, TRUE );
}
else
{
// Receive 할당 패킷 해제
ReleaseRecvPacket( lpOverlapPlus );
}
}
break;
case ClientIoWrite:
ReleaseSendPacket( lpOverlapPlus );
break;
default:
ShowMessage(DOIOSWITCH_FAILED);
assert(0);
break;
}
return TRUE;
}
LPOVERLAPPEDPLUS NFConnection::PrepareAcptPacket()
{
LPOVERLAPPEDPLUS newolp = NULL;
// get accept overlapped structure and packet buffer.
if(m_pPacketPool->AllocAcptPacket(newolp) == FALSE)
{
ShowMessage(ALLOCACPT_FAILED);
return NULL;
}
// 치명적인 에러
if(!newolp)
{
ShowMessage(PREPAREACPT_FAILED);
return NULL;
}
// clear buffer
memset(&newolp->overlapped , NULL, sizeof(OVERLAPPED));
memset(&newolp->wbuf.buf[0], NULL, sizeof(m_nMaxPacketSize));
// init olp structure
newolp->sckListen = m_sckListener;
newolp->sckClient = m_Socket;
newolp->nConnState = ClientIoAccept;
newolp->pClientConn = (PVOID)this;
newolp->wbuf.len = CONNECT_CHECK_SIZE; // newolp->wbuf.len = MAXPACKETSIZE;
// ** WARNING **
// When you change your packet certfying correct connection,
// you must change the size of definition 'CONNECT_CHECK_SIZE'.
return newolp;
}
LPOVERLAPPEDPLUS NFConnection::PrepareRecvPacket(UINT srclen)
{
// 치명적인 에러
if(srclen > (UINT)m_nMaxPacketSize)
{
ShowMessage(PREPARERECVSIZE_FAILED);
return NULL;
}
LPOVERLAPPEDPLUS newolp = NULL;
// get recv overlapped structure and packet buffer.
if( FALSE == m_pPacketPool->AllocRecvPacket(newolp) )
{
ShowMessage(ALLOCRECV_FAILED);
return NULL;
}
// 치명적인 에러
if(!newolp)
{
ShowMessage(PREPARERECV_FAILED);
return NULL;
}
// clear buffer
memset(&newolp->overlapped , NULL, sizeof(OVERLAPPED));
memset(&newolp->wbuf.buf[0], NULL, sizeof(m_nMaxPacketSize));
// init olp structure
newolp->sckListen = m_sckListener;
newolp->sckClient = m_Socket;
newolp->nConnState = ClientIoRead;
newolp->pClientConn = (PVOID) this;
if(srclen == 0) newolp->wbuf.len = m_nMaxPacketSize;
else newolp->wbuf.len = srclen;
return newolp;
}
LPOVERLAPPEDPLUS NFConnection::PrepareSendPacket(CHAR *psrcbuf, UINT srclen)
{
// 치명적인 에러
if(srclen < 0 || srclen > (UINT)m_nMaxPacketSize)
{
ShowMessage(PREPARESENDSIZE_FAILED);
return NULL;
}
LPOVERLAPPEDPLUS newolp = NULL;
// get recv overlapped structure and packet buffer.
if( FALSE == m_pPacketPool->AllocSendPacket(newolp) )
{
ShowMessage(ALLOCSEND_FAILED);
return NULL;
}
// 치명적인 에러
if(!newolp)
{
ShowMessage(PREPARESEND_FAILED);
return NULL;
}
// clear buffer
memset(&newolp->overlapped , NULL, sizeof(OVERLAPPED));
memset(&newolp->wbuf.buf[0], NULL, sizeof(m_nMaxPacketSize));
// init olp structure
newolp->sckListen = m_sckListener;
newolp->sckClient = m_Socket;
newolp->nConnState = ClientIoWrite;
newolp->pClientConn = (PVOID) this;
newolp->wbuf.len = srclen;
memcpy(newolp->wbuf.buf,psrcbuf,srclen);
return newolp;
}
BOOL NFConnection::ReleaseAcptPacket(LPOVERLAPPEDPLUS olp)
{
if(NULL == olp) return FALSE;
if(NULL == olp->wbuf.buf) return FALSE;
if(!m_pPacketPool->FreeAcptPacket(olp))
{
ShowMessage(RELEASEACPT_FAILED);
return FALSE;
}
return TRUE;
}
BOOL NFConnection::ReleaseRecvPacket(LPOVERLAPPEDPLUS olp)
{
if(olp == NULL) return FALSE;
if(olp->wbuf.buf == NULL) return FALSE;
if(!m_pPacketPool->FreeRecvPacket(olp))
{
ShowMessage(RELEASERECV_FAILED);
return FALSE;
}
return TRUE;
}
BOOL NFConnection::ReleaseSendPacket(LPOVERLAPPEDPLUS olp)
{
if(olp == NULL) return FALSE;
if(olp->wbuf.buf == NULL) return FALSE;
if(!m_pPacketPool->FreeSendPacket(olp))
{
ShowMessage(RELEASESEND_FAILED);
return FALSE;
}
return TRUE;
}
BOOL NFConnection::BindIOCP(LPOVERLAPPEDPLUS lpOverlapPlus)
{
// 치명적인 에러
if(!lpOverlapPlus)
{
ShowMessage(BINDIOCP_FAILED);
return FALSE;
}
INT locallen, remotelen;
sockaddr_in * plocal = 0,
* premote = 0;
GetAcceptExSockaddrs(
&(lpOverlapPlus->wbuf.buf[0]),
m_nMaxBuf,
sizeof(sockaddr_in) + 16,
sizeof(sockaddr_in) + 16,
(sockaddr **)&plocal, // 서버단
&locallen,
(sockaddr **)&premote, // 로컬단
&remotelen
);
memcpy(&m_Local, plocal, sizeof(sockaddr_in));
memcpy(&m_Peer, premote, sizeof(sockaddr_in));
if(CreateIoCompletionPort((HANDLE)lpOverlapPlus->sckClient,m_hIOCP,0,0) == 0) return FALSE;
return TRUE;
}
void NFConnection::SetClose_Open(LPOVERLAPPEDPLUS lpOverlapPlus, BOOL bForce)
{
if(m_eConnectFlag != CONNECT_NONE)
{
LOG_ERROR((L"NFConnection::SetClose_Open() m_eConnectFlag == %d", (int)m_eConnectFlag));
}
// 할당 패킷 상태 검사후 패킷 할당 해제
if(NULL != lpOverlapPlus)
{
if(NULL != lpOverlapPlus->wbuf.buf && NULL != m_pPacketPool)
{
// 마지막으로 완료 되었던 오버랩구조체와 버퍼를 릴리즈한다.
switch( lpOverlapPlus->nConnState)
{
case ClientIoAccept:
ReleaseAcptPacket( lpOverlapPlus );
break;
case ClientIoRead:
ReleaseRecvPacket( lpOverlapPlus );
break;
case ClientIoWrite:
ReleaseSendPacket( lpOverlapPlus );
break;
default:
break;
}
}
}
m_bForce = bForce;
InterlockedExchange((LONG*)&m_eConnectFlag,CLOSEOPEN_TRUE);
NFUpdateManager::GetInstance().Add(this, NULL);
}
void NFConnection::SetConnectFlag(CONNECT_EVENT eState)
{
if(m_eConnectFlag != CONNECT_NONE)
{
LOG_ERROR((L"NFConnection::SetConnectFlag() m_eConnectFlag == %s", (int)m_eConnectFlag));
}
InterlockedExchange((LONG*)&m_eConnectFlag,eState);
NFUpdateManager::GetInstance().Add(this, NULL);
}
BOOL NFConnection::DispatchPacket(LPOVERLAPPEDPLUS lpOverlapPlus)
{
// Read같은경우 RecvPost 할때 마다 1번 발생하는데 현재
// Read할때 RecvPost를 1번만 하기 대문에 스레드가 아무리 많아도.DispatchPacket은 1번만 일어난다.
CHAR* psrcbuf = &( lpOverlapPlus->wbuf.buf[0] );
INT srclen = lpOverlapPlus->dwBytes;
// Packet정보 자체가 [H 2byte][P size] 형식이다.
m_RecvIO.Append(psrcbuf, srclen);
m_RecvIO.Lock();
// IOCP는 스레드 패킷처리에 의한 성능향상이 주 능력이다
// 그런데 아래와 같이 UpdateManaget에 패킷을 넣은후 주 스레드에서 Update를 처리하면
// 데드락같은 문제는 생기지 않지만 다중처리에 의한 성능향상이 생기지 않는다.
// 패킷은 스레드 상태에서 바로 처리하게 수정하고 UpdateManager은 커넥트 플래스를
// 업데이트 하는걸로 제한해보자.
#ifdef ENABLE_UPDATEQUE
if(m_RecvIO.GetPacket(&m_RecvPacket) == 1)
{
m_RecvPacket.DecryptPacket();
if(m_RecvPacket.IsAliveChecksum())
NFUpdateManager::GetInstance().Add(this, &m_RecvPacket);
m_RecvPacket.Init();
}
else
m_RecvIO.UnLock();
#else
// 아래와 같이 스레드에서 패킷을 처리하게 되면
// Dispatch에 크리티컬 세션을 집어넣어 데드락에 주의해야한다.
if(m_RecvIO.GetPacket(&m_RecvPacket) == 1)
{
m_RecvPacket.DecryptPacket();
if(m_RecvPacket.IsAliveChecksum())
{
DispatchPacket(m_RecvPacket);
}
m_RecvPacket.Init();
}
else
m_RecvIO.UnLock();
#endif
// 그리고 새로운 recieve buffer를 준비하여 Post한다.
return RecvPost();
}
VOID NFConnection::UpdatePacket(NaveNet::NFPacket& Packet)
{
if(Packet.GetCommand() != 0)
{
DispatchPacket(Packet);
return;
}
// 커넥션의 상태를 업데이트 하기위한 부분.
if(m_eConnectFlag == CONNECT_NONE)
return;
if(m_eConnectFlag == CONNECT_TRUE)
{
InterlockedExchange((LONG*)&m_eConnectFlag,CONNECT_NONE);
OnConnect(TRUE);
}
else if(m_eConnectFlag == CONNECT_FALSE)
{
InterlockedExchange((LONG*)&m_eConnectFlag,CONNECT_NONE);
OnConnect(FALSE);
Close_Open();
}
else if(m_eConnectFlag == DISCONNECT_TURE)
{
InterlockedExchange((LONG*)&m_eConnectFlag,CONNECT_NONE);
Disconnect(FALSE);
}
else if(m_eConnectFlag == CLOSEOPEN_TRUE)
{
InterlockedExchange((LONG*)&m_eConnectFlag,CONNECT_NONE);
Close_Open(m_bForce);
}
}
BOOL NFConnection::SendPost( CHAR* pPackte, INT Len )
{
if(!m_Socket) return FALSE;
if(!IsConnect()) return FALSE;
if(m_Socket == NULL || IsConnect() == FALSE)
{
ShowMessage(SENDPOST_FAILED);
return FALSE;
}
// prepare recieve buffer
LPOVERLAPPEDPLUS newolp = PrepareSendPacket(pPackte,Len);
// 제대로 할당 받았는지 조사
if(newolp == NULL) return FALSE;
INT ret = WSASend( newolp->sckClient,
&newolp->wbuf,
1,
&newolp->dwBytes, // 만약 호출했을때 바로 받았다면 여기로 받은 크기가 넘어오지만 iocp에서는 의미가 없다.
newolp->dwFlags,
&newolp->overlapped, // Overlapped 구조체
NULL );
// 에러 처리
if(ret == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
{
ShowMessage(SENDPOSTPENDING_FAILED);
ReleaseSendPacket(newolp);
return FALSE;
}
return TRUE;
}
BOOL NFConnection::SendPost( NaveNet::NFPacket& Packet ) // 실제 Send 처리
{
// 보내기 직전 체크섬을 생성한다.
Packet.EncryptPacket();
INT Len = Packet.m_Header.Size;
CHAR* pPacket = (CHAR*)&Packet;
return SendPost(pPacket, Len);
}
BOOL NFConnection::RecvPost(UINT buflen)
{
if(m_Socket == NULL || IsConnect() == FALSE)
{
ShowMessage(RECVPOST_FAILED);
return FALSE;
}
// prepare recieve buffer
LPOVERLAPPEDPLUS newolp = PrepareRecvPacket(buflen);
// 제대로 할당 받았는지 조사
if(newolp == NULL) return FALSE;
INT ret = WSARecv( newolp->sckClient,
&newolp->wbuf,
1,
&newolp->dwBytes, // 만약 호출했을때 바로 받았다면 여기로 받은 크기가 넘어오지만 iocp에서는 의미가 없다.
&newolp->dwFlags,
&newolp->overlapped, // Overlapped 구조체
NULL );
// 에러 처리
if(ret == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
{
ShowMessage(RECVPOSTPENDING_FAILED);
ReleaseRecvPacket(newolp);
return FALSE;
}
return TRUE;
}
BOOL NFConnection::GetClientIP(INT *iIP)
{
if(iIP == NULL) return FALSE;
if(!IsConnect())
{
iIP[0] = 0;
return FALSE;
}
iIP[0] = m_Peer.sin_addr.S_un.S_un_b.s_b1;
iIP[1] = m_Peer.sin_addr.S_un.S_un_b.s_b2;
iIP[2] = m_Peer.sin_addr.S_un.S_un_b.s_b3;
iIP[3] = m_Peer.sin_addr.S_un.S_un_b.s_b4;
return TRUE;
}
BOOL NFConnection::GetClientIP(CHAR *szIP)
{
if(szIP == NULL) return FALSE;
if(!IsConnect())
{
szIP[0] = NULL;
return FALSE;
}
sprintf(szIP,"%d.%d.%d.%d",(INT)m_Peer.sin_addr.S_un.S_un_b.s_b1,
(INT)m_Peer.sin_addr.S_un.S_un_b.s_b2,
(INT)m_Peer.sin_addr.S_un.S_un_b.s_b3,
(INT)m_Peer.sin_addr.S_un.S_un_b.s_b4);
return TRUE;
}
BOOL NFConnection::GetClientIP(WCHAR *szIP)
{
if(szIP == NULL) return FALSE;
if(!IsConnect())
{
szIP[0] = NULL;
return FALSE;
}
swprintf(szIP, L"%d.%d.%d.%d",(INT)m_Peer.sin_addr.S_un.S_un_b.s_b1,
(INT)m_Peer.sin_addr.S_un.S_un_b.s_b2,
(INT)m_Peer.sin_addr.S_un.S_un_b.s_b3,
(INT)m_Peer.sin_addr.S_un.S_un_b.s_b4);
return TRUE;
}
BOOL NFConnection::GetClientIP(sockaddr_in& addr)
{
if(!IsConnect())
{
memcpy(&addr,0,sizeof(sockaddr_in));
return FALSE;
}
CopyMemory((CHAR*)&addr,(CHAR*)&m_Peer,sizeof(sockaddr_in));
return TRUE;
}
VOID NFConnection::Disconnect(BOOL bForce)
{
// 연결 되어있는지 확인
if(!IsConnect())
return;
// 변수 초기화
InterlockedExchange((LONG*)&m_eConnectFlag,CONNECT_NONE);
InterlockedExchange((LONG*)&m_bIsConnect,FALSE);
m_uRecvTickCnt = 0;
m_bForce = FALSE;
// 소켓과 리스너 상태 확인
if(m_Socket)
{
struct linger li = {0, 0}; // Default: SO_DONTLINGER
shutdown(m_Socket, SD_BOTH );
// 소켓에 처리 되지 않은 데이타가 소켓 버퍼에 남아있다면,
if(bForce) li.l_onoff = 1; // SO_LINGER, timeout = 0
// 잔여 데이타가 있으면 제거
setsockopt(m_Socket, SOL_SOCKET, SO_LINGER, (CHAR *)&li, sizeof(li));
closesocket(m_Socket); // 소켓 닫기
m_Socket = NULL; // 초기화
ShowMessage(CLOSE_SOCKET);
}
OnDisconnect();
Clear();
}
BOOL NFConnection::IsConnect()
{
BOOL bRet = m_bIsConnect;
return bRet;
}
LONG NFConnection::GetRecvTickCnt()
{
LONG lRecvTickCount = m_uRecvTickCnt;
return lRecvTickCount;
}
}