#include "NFNet.h" #include "NFNetClientS.h" namespace NaveNet { NFNetClientS::NFNetClientS() : m_hSocket(NULL), m_nPort(0), m_hEventThread(NULL), m_hEvent(NULL), m_bConnect(FALSE), m_bClose(FALSE) { m_SendQueue.Create(64); m_RecvQueue.Create(256); m_RecvIO.NewIOBuf(0); // 0À¸·Î ÇÏ¸é ±âº»ÀûÀ¸·Î DefaultPacketSize * 1024 ZeroMemory(m_strIPAddr, sizeof(m_strIPAddr)); // Server IPÀúÀå WinSockInit(); } NFNetClientS::~NFNetClientS() { // ´Ù½Ã Ä¿³ÝÀ» Á¾·á // m_bConnect = TRUE; // Connect º¯¼ö º¯°æ // CloseAll(); OnClose(); Stop(); // Á¾·á ÇÔ¼ö È£Ãâ // ¹öÆÛ»èÁ¦ m_SendQueue.Release(); m_RecvQueue.Release(); m_RecvIO.DeleteIOBuf(); WSACleanup(); } BOOL NFNetClientS::WinSockInit() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { WSACleanup(); // Tell the user that we could not find a usable // WinSock DLL. return FALSE; } if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { // Tell the user that we could not find a usable // // WinSock DLL. // WSACleanup( ); return FALSE; } return TRUE; } BOOL NFNetClientS::Init( LPCSTR szIP, int nPort ) { m_nPort = nPort; // Æ÷Æ® ¹øÈ£ unsigned long dwThreadId = 0; // ½º·¹µå »ý¼ºÀ» À§ÇÑ º¯¼ö // ip ¾îµå·¹½º IN_ADDR LoginAddress; if (GetHostIPByDomain(LoginAddress, szIP)) strncpy(m_strIPAddr, inet_ntoa(LoginAddress), 32); else strncpy(m_strIPAddr, szIP, 32); // ¿¬°áÀ» ½ÃŲ´Ù. ¼­¹ö·Î.. ¸¸¾à ¼­¹ö¿¬°á¿¡ ½ÇÆÐÇÑ´Ù¸é // Netword Event ¿¡¼­ FW_CLOSE°¡ ¹ß»ýÇØ ¼ÒÄÏÀÌ CloseµÈ´Ù. if(!Connect()) { // ½ÇÆÐÇßÀ»°æ¿ì Á¾·áÇÑ´Ù. Sleep(100); // Sleep... OnClose(); //LOG_ERROR((L"ClientCtrl Init Faild.")); return FALSE; } m_bClose = FALSE; m_hEventThread = (HANDLE)CreateThread(NULL, // Security 0, // Stack size - use default EventThreadProc, // Thread fn entry point (void*) this, 0, // Init flag &dwThreadId); // Thread address return TRUE; } void NFNetClientS::Disconnect() { // ÀÌ°Ç ¹«Á¶°Ç CloseÇØÁà¾ßÇϱ⠶§¹®¿¡ CloseAll() È£ÃâÇÏÁö ¾Ê°í Á÷Á¢ ²ö´Ù. OnClose(); Stop(); // Á¾·á ÇÔ¼ö È£Ãâ } void NFNetClientS::Stop() { if (m_hSocket) { struct linger li = {0, 0}; // Default: SO_DONTLINGER li.l_onoff = 1; // SO_LINGER, timeout = 0 shutdown(m_hSocket, SD_BOTH ); // ¿ÀÀ×? ÀÌ°Ô ¹¹Áö? ^^;; ´ã¿¡ ã¾Æº¸ÀÚ // 2001³â 9¿ù 6ÀÏ // Ŭ·ÎÁî ¼ÒÄÏ Àü¿¡ Å¥µÈ µ¥ÀÌŸ¸¦ º¸³¾Áö ¸»Áö °áÁ¤ÇÏ´Â ¿É¼Ç setsockopt(m_hSocket, SOL_SOCKET, SO_LINGER, (CHAR *)&li, sizeof(li)); closesocket(m_hSocket); // ¼ÒÄÏ ´Ý±â m_hSocket = NULL; } if(m_hEventThread) CloseHandle(m_hEventThread); m_hEventThread = NULL; if(m_hEvent) WSACloseEvent(m_hEvent); m_hEvent = NULL; } void NFNetClientS::CloseAll() { if(m_bConnect) { OnClose(); Stop(); // Á¾·á ÇÔ¼ö È£Ãâ } } void NFNetClientS::UpdateQue() { while(GetQueCnt() != 0) { // ÆÐŶÀÌ Àü´ÞµÆ´ÂÁö °Ë»ç. NFPacket* pPacket = NULL; int Cnt = GetPacket(&pPacket); /* // »çÀÌÁî°¡ 0º¸´Ù À۰ųª Packet °¡ NULLÀ̸é. if(Cnt <= 0 || pPacket == NULL) { //LOG_ERROR((L"NFNetClientS::UpdateQue() Packet Error")); //assert( "NFNetClientS::UpdateQue() Packet Error."); } */ // ÇÔ¼ö È£Ãâ ProcessPacket(pPacket, Cnt); // ÆÐŶ Á¦°Å PopPacket(); } } void NFNetClientS::Update() { if(!m_bConnect) return; UpdateQue(); OnSendPacketData(); OnReadPacketData(); } BOOL NFNetClientS::OnClose() { m_bClose = TRUE; m_bConnect = FALSE; // Connect º¯¼ö º¯°æ // ½ÇÁ¦ ÆÄÀÏ OnSocketEvent(WM_SOCK_CLOSE, 0); return FALSE; } BOOL NFNetClientS::Connect() { // ¿¬°áÁßÀ̶ó¸é if(m_bConnect) return TRUE; // ¼ÒÄÏÀÌ ³²¾Æ ÀÖ´Ù¸é Stop(); m_RecvQueue.Reset(); m_SendQueue.Reset(); m_RecvIO.InitIOBuf(); // ¼ÒÄÏ »ý¼º m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // ¼ÒÄÏ »ý¼º °Ë»ç if (m_hSocket == INVALID_SOCKET) { OnSocketEvent(WM_CONNECT, FALSE); return FALSE; } // ³×Æ®¿öÅ© À̺¥Æ® ÇÚµé »ý¼º m_hEvent = WSACreateEvent(); if (m_hEvent == WSA_INVALID_EVENT) { Stop(); return FALSE; } // Request async notification int nRet = WSAEventSelect(m_hSocket, m_hEvent, FD_CLOSE | FD_CONNECT); // ½ÅÈ£¸¦ ¼±º°ÇÏ¿© ¹Þ°Ô ÇÑ´Ù // ¿¡·¯¶ó¸é if (nRet == SOCKET_ERROR) { Stop(); return FALSE; } // ºñµ¿±â ¹æ½Ä unsigned long ul = 1; nRet = ioctlsocket(m_hSocket, FIONBIO, (unsigned long*)&ul); // ¼ÒÄÏ »ý¼º °Ë»ç if (m_hSocket == SOCKET_ERROR) { OnSocketEvent(WM_CONNECT, FALSE); return FALSE; } ///////////////////////////////// // ¼ÒÄÏÀÇ ¼º´É ÃÖÀûÈ­¸¦ À§ÇÑ ¼¼ÆÃ int zero = 0; int err = 0; // Send Buffer¿¡ ´ëÇÑ ¼¼ÆÃ if( (err = setsockopt( m_hSocket, SOL_SOCKET, SO_SNDBUF, (const char*)&zero, sizeof(zero))) == SOCKET_ERROR) { closesocket(m_hSocket); m_hSocket = NULL; return FALSE; } // Receive Buffer¿¡ ´ëÇÑ ¼¼ÆÃ if((err = setsockopt( m_hSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&zero, sizeof(zero) )) == SOCKET_ERROR) { closesocket(m_hSocket); m_hSocket = NULL; return FALSE; } SOCKADDR_IN saServer; memset(&saServer,0,sizeof(saServer)); saServer.sin_family = AF_INET; saServer.sin_addr.s_addr = inet_addr(m_strIPAddr); saServer.sin_port = htons(m_nPort); // ¼­¹ö¿Í Connect nRet = connect(m_hSocket,(sockaddr*)&saServer, sizeof(saServer)); // ¼ÒÄÏ ¿¡·¯À̰ųª ºí·°Å·ÀÌ µÇ¾ú´Ù¸é if (nRet == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) { Stop(); return FALSE; } /* ÀÌ·¸°Ô Connect¸¦ ÇÏ¸é ¼­¹ö´Â AccetpEx°¡ ¼º°øÇÏ¿© ClientSceesionÀº Recv´ë±â»óÅ·Πµé¾î°£´Ù. ¼ÒÄÏ À̺¥Æ®´Â Connect°¡ ¼º°øÇϸé FD_CONNECT¸¦ ¹ß»ý½ÃŲ´Ù. */ return TRUE; } DWORD WINAPI NFNetClientS::EventThreadProc(LPVOID lParam) { // Ŭ·¡½º¸¦ º¯¼ö·Î ¹ÞÀ½ NFNetClientS* pThis = reinterpret_cast(lParam); WSANETWORKEVENTS events; // ³×Æ®¿öÅ© À̺¥Æ® º¯¼ö BOOL bThreadRun = TRUE; // ¹«ÇÑ ·çÇÁ º¯¼ö // ½º·¹µå ¹«ÇÑ ·çÇÁ while(bThreadRun) { if(pThis->m_bClose) { bThreadRun = FALSE; break; } DWORD dwRet; dwRet = WSAWaitForMultipleEvents(1, &pThis->m_hEvent, FALSE, INFINITE, FALSE); if(!pThis->m_hSocket) { // Á¾·á bThreadRun = FALSE; break; } // Figure out what happened int nRet = WSAEnumNetworkEvents(pThis->m_hSocket, pThis->m_hEvent, &events); // ¼ÒÄÏ ¿¡·¯¶ó¸é, if (nRet == SOCKET_ERROR) { //LOG_ERROR((L"EventThread : SOCKET_ERROR, %d", WSAGetLastError()) ); bThreadRun = FALSE; break; } /////////////////// // Handle events // bThreadRun = pThis->NetworkEventHanlder(events.lNetworkEvents); } // À̸®·Î ½º·¹µå°¡ Á¾·á µÇ¸é Server¿¡ ÀÇÇÑ Å¬¶óÀÌ¾ðÆ® Á¾·á!!! <ºñÁ¤»ó Á¾·á> // ½º·¹µå ÃʱâÈ­´Â À§¿¡¼­ ÇØÁֱ⠶§¹®¿¡ ¿©±â¼­ ÇÏÁö´Â ¾Ê´Â´Ù. // pThis->CloseAll(); return 0; } VOID NFNetClientS::OnSendPacketData() { ////////////////////////////////////////////////////////////////////////////// // Send int rc = 0; int idx = 0,size = 0; CHAR* send_temp=NULL; NFPacket Packet; if((size = m_SendQueue.Get(Packet)) != -1) { // ¿©±â¼­ ¾Ïȣȭ ±îÁö °°ÀÌ ÁøÇà ?? // º¸³»±â Á÷Àü üũ¼¶À» »ý¼º. size = Packet.EncryptPacket(); send_temp = (CHAR*)&Packet; while(size > 0) { // 10004 : WSACancelBlockingCall¸¦ È£ÃâÇÏ¿© Â÷´Ü ÀÛ¾÷ÀÌ ÁߴܵǾú½À´Ï´Ù. // 10058 : ÇØ´ç ¼ÒÄÏÀÌ Á¾·áµÇ¾úÀ¸¹Ç·Î µ¥ÀÌÅÍ º¸³»°Å³ª ¹ÞÀ» ¼ö ¾ø½À´Ï´Ù. // 10038 : ¿¬°áÀÌ ²÷¾îÁø ¼ÒÄÏÀ» »ç¿ëÇÒ·Á°í ÇÒ¶§ ³­´Ù. if((rc = send(m_hSocket, &send_temp[idx], size, 0)) == SOCKET_ERROR) { // ºí·°Å· ¿¡·¯¶ó¸é if (GetLastError() != WSAEWOULDBLOCK) // ºí·°Å· ¿¡·¯°¡ ¾Æ´Ï¶ó¸é { //LOG_ERROR((L"SendThread : SOCKET_ERROR, %d", WSAGetLastError())); break; } } else { // ¿¡·¯°¡ ¾ø´Ù¸é size -= rc; idx += rc; } } idx = 0; size = 0; } ////////////////////////////////////////////////////////////////////////////// } VOID NFNetClientS::OnReadPacketData() { ////////////////////////////////////////////////////////////////////////////// // Recv int Ret = recv(m_hSocket, m_RecvBuffer, DEF_MAXPACKETSIZE, 0); // µ¥ÀÌŸ Receive if(Ret == 0) // Graceful close { CloseAll(); return; } else if (Ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK ) // ºí·°Å· ¿¡·¯°¡ ¾Æ´Ï¶ó¸é { //LOG_ERROR((L"[Recv] Packet Size Error : SOCKET_ERROR, %d", WSAGetLastError())); CloseAll(); return; } if(m_RecvIO.Append(m_RecvBuffer, Ret) == -1) { //LOG_ERROR((L"m_RecvIO.Append : Buffer Overflow..") ); } // ¹ÞÀº ÆÐŶÀº IOBuffer¿¡ ³Ö¾î ó¸®ÇÑ´Ù. if(m_RecvIO.GetPacket(&m_RecvPacket) == 1) { m_RecvPacket.DecryptPacket(); if(m_RecvPacket.IsAliveChecksum()) { // ¿©±â¼­ ÇÑÆÐŶ ó¸® ·çƾ È£Ãâ m_RecvQueue.Add(m_RecvPacket); // Message Type À϶§ À̰ɷΠº¸³½´Ù. // ¸¸¾à Update À̺¥Æ® È£ÃâÀ̸é ÀÌ ·çƾÀ» ÁÖ¼®Ã³¸® ÇØÁØ´Ù. OnSocketEvent(WM_RECV_MSG, m_RecvPacket.m_Header.Size); } m_RecvPacket.Init(); } } BOOL NFNetClientS::NetworkEventHanlder(LONG lEvent) { BOOL bFlag = TRUE; // if(lEvent & FD_READ) // { // bFlag = OnReadPacketData(); // } if(lEvent & FD_CLOSE) { bFlag = FALSE; } if(lEvent & FD_CONNECT) { bFlag = OnConnect(); } return bFlag; } BOOL NFNetClientS::OnConnect() { ////////////////////////////////////////////////////////// // IOCP Ȱ¼º ////////////////////////////////////////////////////////// int ErrorCode = send(m_hSocket, (const char*)CONNECT_CHECK_DATA,CONNECT_CHECK_SIZE,0); if(ErrorCode == SOCKET_ERROR) { m_bConnect = FALSE; // ¿¬°á º¯¼ö ¼³Á¤ OFF } else { m_bConnect = TRUE; // ¿¬°á º¯¼ö ¼³Á¤ ON } OnSocketEvent(WM_CONNECT, m_bConnect); return m_bConnect; } int NFNetClientS::GetQueCnt() { return m_RecvQueue.GetQueCnt(); } int NFNetClientS::GetPacket(NFPacket** Packet) { return m_RecvQueue.GetPnt(Packet); } void NFNetClientS::PopPacket() { m_RecvQueue.Del(); } BOOL NFNetClientS::SendPost(NFPacket& Packet) { // ¼­¹ö·Î Send Çϱâ.. return m_SendQueue.Add(Packet); } void NFNetClientS::GetLocalIP(CHAR* LocalIP) { CHAR name[256]; CHAR* TempIp; PHOSTENT hostinfo; WinSockInit(); if( gethostname ( name, sizeof(name)) == 0) { if((hostinfo = gethostbyname(name)) != NULL) { TempIp = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list); strcpy(LocalIP, TempIp); } } } }