#include "stdafx.h" #include "IoHandler.h" #include "Acceptor.h" #include "Connector.h" #include "SessionList.h" #include "SessionPool.h" #include "Session.h" #include "SendBuffer.h" #include "RecvBuffer.h" #include "IOCPServer.h" #include "NetworkObject.h" //================================================================================================== // IoHandler::IoHandler() { ZeroMemory(field_start_pos_, static_cast(field_end_pos_ - field_start_pos_)); } IoHandler::~IoHandler() { if (!shutdown_) { Shutdown(); } for (int i = 0 ; i < (sizeof(io_threads_) / sizeof(io_threads_[0])); ++i) { if (io_threads_[i]) { CloseHandle(io_threads_[i]); } } SAFE_DELETE(accept_session_pool_); SAFE_DELETE(connect_session_pool_); SAFE_DELETE(acceptor_); SAFE_DELETE(connector_); SAFE_DELETE(active_session_list_); SAFE_DELETE(accepted_session_list_); SAFE_DELETE(connect_success_list_); SAFE_DELETE(connect_fail_list_); SAFE_DELETE(temp_session_list_); SAFE_DELETE(temp_session_pending_list_); if (working_slots_for_sender_[0]) { ::free(working_slots_for_sender_[0]); working_slots_for_sender_[0] = 0; }; if (working_slots_for_sender_[1]) { ::free(working_slots_for_sender_[1]); working_slots_for_sender_[1] = 0; }; } void IoHandler::Init(IOCPServer* iocp_server, LPIOHANDLER_DESC description) { iocp_server_ = iocp_server; // Äݹé ÇÔ¼ö Æ÷ÀÎÅÍ À¯È¿¼º °Ë»ç assert(!IsBadReadPtr(description->fnCreateAcceptedObject, sizeof(description->fnCreateAcceptedObject))); assert(!IsBadReadPtr(description->fnDestroyAcceptedObject, sizeof(description->fnDestroyAcceptedObject))); assert(!IsBadReadPtr(description->fnDestroyConnectedObject, sizeof(description->fnDestroyConnectedObject))); // Äݹé ÇÔ¼ö Æ÷ÀÎÅÍ ÀúÀå fnCreateAcceptedObject_ = description->fnCreateAcceptedObject; fnDestroyAcceptedObject_ = description->fnDestroyAcceptedObject; fnDestroyConnectedObject_ = description->fnDestroyConnectedObject; io_handler_key_ = description->dwIoHandlerKey; // ¼¼¼Ç ¸®½ºÆ® »ý¼º active_session_list_ = new SessionList; accepted_session_list_ = new SessionList; connect_success_list_ = new SessionList; connect_fail_list_ = new SessionList; temp_session_list_ = new SessionList; temp_session_pending_list_ = new SessionList; // ÃÖ´ë Á¢¼Ó Á¦ÇÑ Àοø max_number_of_accept_sessions_ = description->dwMaxAcceptSession; max_number_of_connect_sessions_ = description->dwMaxConnectSession; // ¼¼¼Ç Ç® »ý¼º accept_session_pool_ = new SessionPool(max_number_of_accept_sessions_, description->dwSendBufferSize, description->dwRecvBufferSize, description->dwMaxPacketSize, description->dwTimeOut, 1, true); connect_session_pool_ = new SessionPool(max_number_of_connect_sessions_, description->dwSendBufferSize, description->dwRecvBufferSize, description->dwMaxPacketSize, description->dwTimeOut, accept_session_pool_->GetLength() + 1, false); ;{ PACKET_HEADER header; header.size = (WORD)description->dwMaxPacketSize; assert((DWORD)header.size == description->dwMaxPacketSize); }; // ÃÖ´ë ÆÐŶ Å©±â ¼³Á¤ max_packet_size_ = description->dwMaxPacketSize; //---------------------------------------------------------------------------------------------- // NOTE: f110615.3L, added array to switch valid active list if (DWORD max_number_of_sessions = accept_session_pool_->GetNumberOfNodes() + connect_session_pool_->GetNumberOfNodes()) { number_of_working_list_nodes_for_sender_ = max_number_of_sessions; size_t size_of_array = sizeof(Session*) * (max_number_of_sessions + 1); working_slots_for_sender_[0] = reinterpret_cast(::malloc(size_of_array)); working_slots_for_sender_[1] = reinterpret_cast(::malloc(size_of_array)); ZeroMemory(working_slots_for_sender_[0], size_of_array); ZeroMemory(working_slots_for_sender_[1], size_of_array); // oooo\0 - \0 is end delimiter working_list_for_sender_ = working_slots_for_sender_[0]; }; //---------------------------------------------------------------------------------------------- // IOCP »ý¼º iocp_handle_ = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); // IO ¿öÄ¿ ¾²·¹µå »ý¼º assert(description->dwNumberOfIoThreads <= MAX_IO_WORKER_THREAD); number_of_io_threads_ = description->dwNumberOfIoThreads; for (DWORD i = 0; i < number_of_io_threads_; ++i) { unsigned int thread_id; io_threads_[i] = (HANDLE)_beginthreadex(NULL, 0, io_thread, this, 0, &thread_id); } // NOTE: the number of thread contexts are enough // to support the acceptor and the connector with each one. // ¾ï¼ÁÅÍ »ý¼º acceptor_ = new Acceptor; acceptor_->Init(this, (description->dwNumberOfAcceptThreads ? 1 : 0)); // Ä¿³ØÅÍ »ý¼º connector_ = new Connector; connector_->Init(this, (description->dwNumberOfConnectThreads ? 1 : 0)); } DWORD IoHandler::Connect(NetworkObject* network_object, char* ip_string, WORD port) { // ÇØ´ç NetworkObjectÀÇ ¼ÒÄÏÀÌ ÀÌ¹Ì Ä¿³ØÆ® ½ÃµµÁßÀÌ¸é ¸®ÅÏÇÑ´Ù. if (network_object->session_ != NULL) { return 0; } // ¼ÒÄÏ »ý¼º SOCKET hSOCKET = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); // ÁÖ¼Ò ¼ÂÆÃ SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(ip_string); addr.sin_port = htons(port); // ¼¼¼Ç ÇÒ´ç Session* session = AllocConnectSession(); assert((session != NULL) && "¼¼¼ÇÀÌ ¸ðÀÚ¶ó¼­ Connect ÇÒ ¼ö ¾ø½À´Ï´Ù. dwMaxConnectSession °³¼ö¸¦ È®ÀÎÇØÁÖ¼¼¿ä"); // ¼¼¼Ç¿¡ ¼ÒÄÏ ¹× ÁÖ¼Ò ¼ÂÆÃ session->SetSocket(hSOCKET); session->SetSockAddr(addr); // ¼¼¼ÇÀ» ³×Æ®¿÷ ¿ÀºêÁ§Æ®¿Í ¹ÙÀεù assert(network_object != NULL); session->BindNetworkObject(network_object); connector_->Connect(session); return session->GetIndex(); } //================================================================================================== /** @remarks ¸®½¼ ¼ÒÄÏÀ» »ý¼ºÇÏ°í ¸®½¼À» ½ÃÀÛÇÑ´Ù. @retval BOOL ¸®½¼ ¼ÒÄÏ »ý¼º¿¡ ½ÇÆÐÇϸé false¸¦ ¸®ÅÏÇÑ´Ù. @param ip_string ¸®½¼¿¡ »ç¿ëÇÒ IP @param port ¸®½¼¿¡ »ç¿ëÇÒ Æ÷Æ® */ //================================================================================================== BOOL IoHandler::StartListen(char* ip_string, WORD port) { assert(max_number_of_accept_sessions_ > 0); // ÀÌ¹Ì ¸®½¼ÁßÀ̶ó¸é ¼º°ø ó¸® if (IsListening()) { return true; } if (!acceptor_->StartListen(ip_string, port)) { assert(!"Listen socket creation failed."); return false; } while (Session* session = AllocAcceptSession()) { session->PreAccept(acceptor_->GetListenSocket()); } return true; } BOOL IoHandler::IsListening() { return acceptor_->IsListening(); } void IoHandler::SuspendListenThread() { acceptor_->SuspendListenThread(); } void IoHandler::ResumeListenThread() { acceptor_->ResumeListenThread(); } ///--------------------------------------------------------------------------- ///--------------------------------------------------------------------------- // ´ã´ö Ãß°¡. ¼¼¼ÇÀ» ¾ò¾î¼­ ±× ¼¼¼ÇÀÇ SendBuffer Á¤º¸¸¦ º¸±âÀ§Çؼ­ ¸¸µé¾úÀ½! ///--------------------------------------------------------------------------- ///--------------------------------------------------------------------------- Session* IoHandler::GetSession(DWORD session_index) { SESSION_LIST::iterator end = active_session_list_->end(); for (SESSION_LIST::iterator it=active_session_list_->begin() ; it != end ; ++it) { Session* session = *it; if (session->GetIndex() == session_index) { return session; } } return NULL; } //================================================================================================== /** @remarks »ç¿ëÁßÀÌ´ø ¼¼¼ÇµéÀ» ¸ðµÎ ¼¼¼ÇÇ®¿¡ ¹ÝȯÇÑ´Ù. */ //================================================================================================== Session* IoHandler::AllocAcceptSession() { if (Session* session = accept_session_pool_->Alloc()) { session->Init(); return session; }; return NULL; } Session* IoHandler::AllocConnectSession() { if (Session* session = connect_session_pool_->Alloc()) { session->Init(); return session; }; return NULL; } void IoHandler::FreeSession(Session* session) { //printf("[FreeSession][%d]\n", (int)session->GetSocket()); // NOTE: f110615.2L, the calling of Session::Init() moved to process on resource allocation. session->CloseSocket(); if (session->IsAcceptSocket()) { accept_session_pool_->Free(session); } else { connect_session_pool_->Free(session); } } void IoHandler::ReuseSession(Session* session) { //printf("[ReuseSession][%d]\n", (int)session->GetSocket()); session->Reuse(iocp_handle_); } //================================================================================================== /** @remarks Á¢¼Ó¿¡ ¼º°øÇÑ ¼¼¼Ç ¸®½ºÆ® ó¸® @par ConnectSuccessList¿¡ ÀÖ´Â ¼¼¼ÇµéÀ» IOCP¿¡ µî·ÏÇϰí OnConnect(true)¸¦ È£ÃâÇϰí ActiveSessionList¿¡ Ãß°¡ÇÑ´Ù. */ //================================================================================================== void IoHandler::ProcessConnectSuccessList() { // Ä¿³ØÆ®¿¡ ¼º°øÇÑ ¼¼¼ÇµéÀ» Àӽà ¸®½ºÆ®·Î ¿Å±è connect_success_list_->Lock(); temp_session_list_->splice(temp_session_list_->end(), *connect_success_list_); connect_success_list_->Unlock(); //---------------------------------------------------------------------------------------------- SESSION_LIST::iterator it = temp_session_list_->begin(); SESSION_LIST::const_iterator end = temp_session_list_->end(); while (it != end) { Session* const session = *it; // IOCP¿¡ ÇÚµé µî·Ï CreateIoCompletionPort((HANDLE)session->GetSocket(), iocp_handle_, (ULONG_PTR)session, 0); session->Init(); if (session->PreRecv() == false) { session->OnLogString("[ProcessConnectSuccessList] PreRecv Fail!"); it = temp_session_list_->erase(it); // ¼¼¼Ç Ç®¿¡ ¹Ýȯ FreeSession(session); session->OnConnect(false); continue; }; // success session->OnConnect(true); ++it; }; //---------------------------------------------------------------------------------------------- if (temp_session_list_->empty() == false) { // µ¿Á¢¼ö Áõ°¡ number_of_connect_sessions_ += (DWORD)temp_session_list_->size(); // Ä¿³ØÆ®¿¡ ¼º°øÇÑ ¼¼¼ÇµéÀ» ActiveSessionList¿¡ Ãß°¡ÇÑ´Ù. active_session_list_->Lock(); active_session_list_->splice(active_session_list_->end(), *temp_session_list_); active_session_list_->Unlock(); }; } //================================================================================================== /** @remarks Á¢¼Ó¿¡ ½ÇÆÐÇÑ ¼¼¼Ç ¸®½ºÆ® ó¸® @par ConnectFailList¿¡ ÀÖ´Â ¼¼¼Çµé¿¡ ´ëÇØ OnConnect(false)À» È£ÃâÇÑ´Ù. */ //================================================================================================== void IoHandler::ProcessConnectFailList() { connect_fail_list_->Lock(); SESSION_LIST::iterator end = connect_fail_list_->end(); for (SESSION_LIST::iterator it = connect_fail_list_->begin(); it != end ; ++it) { Session* session = *it; // ¼¼¼Ç Ç®¿¡ ¹Ýȯ FreeSession(session); session->OnConnect(false); } connect_fail_list_->clear(); connect_fail_list_->Unlock(); } //================================================================================================== /** @remarks TempSessionList¿¡ ÀÖ´Â ¼¼¼ÇµéÀ» IOCP¿¡ µî·ÏÇϰí ActiveSessionList·Î ¿Å±â°í OnAccpet()¸¦ È£ÃâÇÑ´Ù. */ //================================================================================================== void IoHandler::ProcessAcceptedSessionList() { // Á¢¼Ó¿¡ ¼º°øÇÑ ¼¼¼ÇµéÀ» ¹Þ¾ÆµÐ Àӽà ¸®½ºÆ®·Î ¿Å±è accepted_session_list_->Lock(); temp_session_list_->splice(temp_session_list_->end(), *accepted_session_list_); accepted_session_list_->Unlock(); SESSION_LIST::iterator end = temp_session_list_->end(); // Á¢¼Ó¿¡ ¼º°øÇÑ ¼¼¼Ç¿¡ ´ëÇÑ Ã³¸® for (SESSION_LIST::iterator it = temp_session_list_->begin(); it != end;) { Session* session = *it; // ÃÖ°íµ¿Á¢¼ö¸¦ ÃʰúÇÏ´Â °æ¿ì ½ÇÆÐ if (number_of_accept_sessions_ >= max_number_of_accept_sessions_) { session->OnLogString("connection full! no available accept socket!"); it = temp_session_list_->erase(it); ReuseSession(session); continue; } // IOCP¿¡ ÇÚµé µî·Ï CreateIoCompletionPort((HANDLE)session->GetSocket(), iocp_handle_, (ULONG_PTR)session, 0); // Recv¿¡ ½ÇÆÐÇÏ´Â °æ¿ì ó¸® if (!session->PreRecv()) { session->OnLogString("[ProcessAcceptedSessionList] PreRecv Fail!"); it = temp_session_list_->erase(it); ReuseSession(session); continue; } //-------------------------------- // ¼º°øÀûÀ¸·Î Á¢¼ÓµÈ ¼¼¼Ç ó¸® //-------------------------------- // ³×Æ®¿÷ ¿ÀºêÁ§Æ® »ý¼º ¿äû NetworkObject* network_object = fnCreateAcceptedObject_(); assert(network_object); // ³×Æ®¿÷ ¿ÀºêÁ§Æ® ¹ÙÀεù session->BindNetworkObject(network_object); // Á¢¼Ó½Ã ÃʱâÈ­ ¹× NetworkObject·Î Á¢¼Ó ÅëÁö session->OnAccept(); // µ¿Á¢¼ö Áõ°¡ ++number_of_accept_sessions_; // last ++it; } if (!temp_session_list_->empty()) { // Á¢¼Ó¿¡ ¼º°øÇÑ ¼¼¼ÇµéÀ» ActiveSessionList¿¡ Ãß°¡ active_session_list_->Lock(); active_session_list_->splice(active_session_list_->begin(), *temp_session_list_); active_session_list_->Unlock(); } } //================================================================================================== /** @remarks ÇöÀç accept ¶Ç´Â connectµÇ¾î Ȱ¼ºÈ­µÈ ¼¼¼ÇµéÀ» ¼øÈ¸ÇÏ¸ç ¹ÞÀº ÆÐŶ µîÀ» ó¸®ÇÑ´Ù. */ //================================================================================================== void IoHandler::ProcessActiveSessionList() { SESSION_LIST::iterator end = active_session_list_->end(); for (SESSION_LIST::iterator it = active_session_list_->begin(); it!=end ; ++it) { Session* session = *it; if (session->ShouldBeRemoved()) { continue; } if (session->HasDisconnectOrdered()) { // º¸³»±â ¹öÆÛ¸¦ ºñ¿ì°í ²÷¾î¾ß ÇÏ´Â ¼¼¼ÇÀÇ Ã³¸® // NOTE: f110623.5L, added condition to prevent the deadlocked state. SendBuffer* const send_buffer = session->GetSendBuffer(); if (bool empty_buffer = send_buffer->IsEmpty()) { #ifdef __SUSUNLOVE_REMOVE_ONLOGSTRING_APPLY_20080110 session->OnLogString("[REMOVE] BufferSize 0 \n"); #else #ifdef _DEBUG session->OnLogString("[REMOVE] BufferSize 0 \n"); #endif #endif session->Remove(); } } else { if (session->IsAcceptSocket() && session->IsOnIdle()) { session->OnLogString("Idle Session is disconnected"); session->Remove(); continue; } // ¹Þ±â ¹öÆÛ ó¸® if (!session->ProcessReceivedPacket(max_packet_size_)) { #ifdef __SUSUNLOVE_REMOVE_ONLOGSTRING_APPLY_20080110 session->OnLogString("[REMOVE] ProcessReceivedPacket\n"); #else #ifdef _DEBUG session->OnLogString("[REMOVE] ProcessReceivedPacket\n"); #endif #endif session->Remove(); } } } // end for } //================================================================================================== /** @remarks ÀÏÁ¤ ½Ã°£ ÀÌ»ó ÆÐŶ ¼Û½ÅÀÌ ¾ø´Â ¼¼¼ÇµéÀ» Á¦°ÅÇÑ´Ù. */ //================================================================================================== void IoHandler::KickDeadSessions() { //---------------------------------------------------------------------------------------------- // NOTE: f110615.3L, added array to switch valid active list Session** working_list = (this->working_list_for_sender_ != working_slots_for_sender_[0]) ? working_slots_for_sender_[0] : working_slots_for_sender_[1]; //---------------------------------------------------------------------------------------------- // Á¦°ÅµÉ ¼¼¼ÇµéÀ» ActiveSessionList¿¡¼­ Á¦°ÅÇϰí Àӽà ¸®½ºÆ®¿¡ ´ã´Â´Ù. active_session_list_->Lock(); ;{ Session** working_list_it = working_list; SESSION_LIST::iterator it = active_session_list_->begin(); SESSION_LIST::const_iterator end = active_session_list_->end(); while (it != end) { Session* session = *it; if (session->ShouldBeRemoved()) { it = active_session_list_->erase(it); temp_session_list_->push_back(session); continue; }; // NOTE: f110616.5L session->ResumeReception(); *working_list_it++ = session; ++it; }; *working_list_it = NULL; }; active_session_list_->Unlock(); // InterlockedExchangePointer((PVOID*)&this->working_list_for_sender_, working_list); // #if 0 active_session_list_->Lock(); ;{ SESSION_LIST::iterator it = active_session_list_->begin(); SESSION_LIST::const_iterator end = active_session_list_->end(); while (it != end) { Session* session = *it; if (session->ShouldBeRemoved()) { it = active_session_list_->erase(it); temp_session_list_->push_back(session); continue; } ++it; } }; active_session_list_->Unlock(); #endif //---------------------------------------------------------------------------------------------- ;{ if (temp_session_pending_list_->empty() == false) { temp_session_list_->splice(temp_session_list_->end(), *temp_session_pending_list_); }; SESSION_LIST::iterator it = temp_session_list_->begin(); SESSION_LIST::const_iterator end = temp_session_list_->end(); // Á¦°ÅµÈ ¼¼¼Çµé¿¡ ´ëÇÑ Ã³¸® while (it != end) { Session* const session = *it; // NOTE: f110623.5L, the below checker has caused the deadlocked state. // 'f110615.1L, to prevent the removing session while sending' that is previous notice // can solve the 'Clear' method. #if 0 // NOTE: f110615.1L, added condition to prevent the removing session while sending. if (SendBuffer* send_buffer = session->GetSendBuffer()) { // NOTE: short-term interlock checking, it may occur // that send_thread has been send preparation after 'session->ShouldBeRemoved()' if (send_buffer->HasBeenSendWorking()) { it = temp_session_list_->erase(it); temp_session_pending_list_->push_back(session); continue; }; }; #endif const bool is_accept_socket = session->IsAcceptSocket(); // µ¿Á¢¼ö °¨¼Ò (is_accept_socket) ? --number_of_accept_sessions_ : --number_of_connect_sessions_; NetworkObject* const network_object = session->GetNetworkObject(); // ³×Æ®¿÷ ¿ÀºêÁ§Æ® ¾ð¹ÙÀεù session->UnbindNetworkObject(); // ÄݹéÇÔ¼ö È£Ãâ Àü¿¡ ¼¼¼ÇÀ» free ÇØÁØ´Ù. ÄÝ¹é ¾È¿¡¼­ Connect¿äûÇÒ ¼öµµ ÀÖÀ¸¹Ç·Î.. // accept¿ë ¼¼¼ÇÀÌ¸é ¼ÒÄÏÀ» Àç»ç¿ëÇÏ¿© ´Ù½Ã accept¸¦ °É°í, connect¿ë ¼¼¼ÇÀ̸é Ç®¿¡ ¹ÝȯÇÑ´Ù. if (is_accept_socket && !shutdown_) { ReuseSession(session); } else { FreeSession(session); } // NetworkObject·Î µð½ºÄ¿³ØÆ® ÅëÁö network_object->OnDisconnect(); // ³×Æ®¿÷ ¿ÀºêÁ§Æ® ¼Ò¸ê ¿äû if (is_accept_socket) { fnDestroyAcceptedObject_(network_object); } else { fnDestroyConnectedObject_(network_object); }; ++it; }; //foreach 'temp_session_list' temp_session_list_->clear(); }; } void IoHandler::ProcessSend() { // need Switch Buffer Logic // ActiveSessionListÀÇ ¼¼¼ÇÀÇ º¸³»±â ÆÛ¹ö Àü¼Û //---------------------------------------------------------------------------------------------- // NOTE: f110615.3L, used array to lockless for each buffer control long number_of_max_working_array = this->number_of_working_list_nodes_for_sender_; Session** io_sessions = this->working_list_for_sender_; while (Session* session = *io_sessions++) { if (number_of_max_working_array-- <= 0) { break; }; if (session->ShouldBeRemoved()) { continue; }; if (session->PreSend() == false) { #ifdef __SUSUNLOVE_REMOVE_ONLOGSTRING_APPLY_20080110 printf("[REMOVE][%d] session->PreSend() == false\n", (int)session->GetSocket()); #endif #ifdef _DEBUG session->OnLogString("[REMOVE][%u] session->PreSend() == false\n", (int)session->GetSocket()); #endif session->Remove(); // À̰ÍÀº active_session_list_ÀÇ Á¦°Å°¡ ¾Æ´Ï¹Ç·Î end°ª º°µµ ÇÒ´çÇØ¼­ »ç¿ëÇÑ´Ù. }; }; #if 0 active_session_list_->Lock(); SESSION_LIST::iterator end = active_session_list_->end(); for (SESSION_LIST::iterator it=active_session_list_->begin(); it!=end ; ++it) { Session* session = *it; if (session->ShouldBeRemoved()) { continue; } if (session->PreSend() == false) { #ifdef __SUSUNLOVE_REMOVE_ONLOGSTRING_APPLY_20080110 printf("[REMOVE][%d] session->PreSend() == false\n", (int)session->GetSocket()); #endif #ifdef _DEBUG session->OnLogString("[REMOVE][%u] session->PreSend() == false\n", (int)session->GetSocket()); #endif session->Remove(); // À̰ÍÀº active_session_list_ÀÇ Á¦°Å°¡ ¾Æ´Ï¹Ç·Î end°ª º°µµ ÇÒ´çÇØ¼­ »ç¿ëÇÑ´Ù. } } active_session_list_->Unlock(); #endif //0 } //================================================================================================== /** @remarks ¸ðµç ¼¼¼ÇµéÀ» Á¦°ÅÇÑ´Ù. */ //================================================================================================== void IoHandler::KickAllSessions() { SESSION_LIST::iterator end = active_session_list_->end(); for (SESSION_LIST::iterator it = active_session_list_->begin(); it != end ; ++it) { Session* session = *it; #ifdef __SUSUNLOVE_REMOVE_ONLOGSTRING_APPLY_20080110 session->OnLogString("[REMOVE] KickAllSessions() \n"); #endif session->Remove(); } } //================================================================================================== /** @remarks AcceptµÈ ¼¼¼Ç°ú ConnectµÈ ¼¼¼ÇµéÀ» IOCP¿¡ µî·ÏÇϸ鼭 ActiveSessionList·Î ¿Å±â°í ¸ðµç ¼¼¼ÇÀÇ ¹Þ±â ¹öÆÛ¸¦ °Ë»çÇÏ¿© ÆÐŶÀ» ó¸®ÇÏ´Â µîÀÇ ÀÛ¾÷À» ÇÑ´Ù. @par ÀÌ ÇÔ¼ö´Â ÁÖ±âÀûÀ¸·Î È£ÃâÇØ ÁÖ¾î¾ß ÇÑ´Ù. */ //================================================================================================== void IoHandler::Update() { ProcessActiveSessionList(); if (!accepted_session_list_->empty()) { ProcessAcceptedSessionList(); } if (!connect_success_list_->empty()) { ProcessConnectSuccessList(); } if (!connect_fail_list_->empty()) { ProcessConnectFailList(); } KickDeadSessions(); } void IoHandler::Shutdown() { shutdown_ = true; KickAllSessions(); ProcessActiveSessionList(); KickDeadSessions(); acceptor_->Shutdown(); connector_->Shutdown(); // IOCP ¾²·¹µå Á¾·á for (DWORD i = 0; i < number_of_io_threads_; ++i) { PostQueuedCompletionStatus(iocp_handle_, 0, 0, NULL); } // IO ¿öÄ¿ ¾²·¹µå°¡ ¸ðµÎ Á¾·áµÉ ¶§±îÁö ±â´Ù¸°´Ù. WaitForMultipleObjects(number_of_io_threads_, io_threads_, true, INFINITE); }