#include "stdafx.h" #include "Acceptor.h" #include "IoHandler.h" #include "IOCPServer.h" #include "Session.h" #include "RecvBuffer.h" #include "SessionList.h" #include "SessionPool.h" #include "MsWinsockUtil.h" Acceptor::Acceptor() { listen_socket_ = INVALID_SOCKET; iocp_handle_ = INVALID_HANDLE_VALUE; for (DWORD i = 0; i < MAX_ACCEPT_THREAD; ++i) { thread_handles_[i] = INVALID_HANDLE_VALUE; } number_of_threads_ = 0; } Acceptor::~Acceptor() { Shutdown(); if (iocp_handle_ != INVALID_HANDLE_VALUE) { CloseHandle(iocp_handle_); } for (DWORD i = 0; i < number_of_threads_; ++i) { if (thread_handles_[i] != INVALID_HANDLE_VALUE) { CloseHandle(thread_handles_[i]); } } } void Acceptor::Init(IoHandler* io_handler, DWORD number_of_threads) { assert(number_of_threads <= MAX_ACCEPT_THREAD); io_handler_ = io_handler; number_of_threads_ = number_of_threads; // Accept¿ë IOCP »ý¼º iocp_handle_ = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); // ¿öÄ¿ ¾²·¹µå »ý¼º unsigned int thread_id; for (DWORD i = 0; i < number_of_threads_; ++i) { thread_handles_[i] = \ (HANDLE)_beginthreadex(NULL, 0, accept_thread, (LPVOID)this, 0/*CREATE_SUSPENDED*/, &thread_id); } // backlog°¡ ´Ù áÀ» ¶§´Â IOCP·Î ¸Þ½ÃÁö¸¦ ¹ÞÀ» ¼ö ¾øÀ¸¹Ç·Î À̺¥Æ® ±â¹Ý ¸®½¼À» Ãß°¡·Î ºÙ¿© Áà¾ß ÇÑ´Ù } //================================================================================================== /** @remarks Æ÷Æ®¸¦ ÃʱâÈ­ÇÑ´Ù. @param ip_string Á¢¼ÓÇÒ IP @param port Á¢¼ÓÇÒ Æ÷Æ® @retval BOOL ¸®½¼¿¡ ½ÇÆÐÇϸé false ¸®ÅÏ */ //================================================================================================== BOOL Acceptor::StartListen(const char* ip_string, WORD port) { // ¸ØÃç ÀÖÀ¸¸é ´Ù½Ã ±¸µ¿½ÃŲ´Ù. ResumeListenThread(); // ¸®½¼ ¼ÒÄÏ »ý¼º if (!CreateListenSocket(ip_string, port)) { return false; } // IOCP¿¡ ¸®½¼ ¼ÒÄÏ µî·Ï CreateIoCompletionPort((HANDLE)listen_socket_, iocp_handle_, 1, 0); //Dll¿¡¼­ ÇÔ¼ö ·Îµå(AcceptEx, TransmitFile) MsWinsockUtil::LoadExtensionFunction(listen_socket_); return true; } //================================================================================================== /** @remarks ¸®½¼ ¼ÒÄÏÀ» »ý¼ºÇϰí ÁÖ¼Ò¸¦ ¼³Á¤ÇÑ´Ù. @retval BOOL ¸®½¼ ¼ÒÄÏ »ý¼º¿¡ ½ÇÆÐÇϸé false¸¦ ¸®ÅÏÇÑ´Ù. (IP¿Í port°¡ °ãÄ¡´Â °æ¿ìÀÏ °ÍÀÌ´Ù.) */ //================================================================================================== BOOL Acceptor::CreateListenSocket(const char* ip_string, WORD port) { // ÀÌ¹Ì ¸®½¼ ¼ÒÄÏÀÌ »ý¼ºµÇ¾î ÀÖÀ¸¸é ½ÇÆÐ if (listen_socket_ != INVALID_SOCKET) { return false; } // ¸®½¼ ¼ÒÄÏ »ý¼º listen_socket_ = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); if (listen_socket_ == INVALID_SOCKET) { return false; } // // IO_PENDINGÁßÀÎ ³ðÀ» ¹ö¸²À¸·Î½á ¼ÒÄÏ Ã³¸® ¼Óµµ¸¦ ³ôÀδÙ. // // À̰ÍÀ» À§ÇØ linger ¿É¼Ç Àû¿ë // LINGER slinger; // // slinger.l_linger = 5000; // slinger.l_onoff = (USHORT)SO_LINGER; // int ret = setsockopt(listen_socket_, SOL_SOCKET, SO_LINGER, (char*)&slinger, sizeof(LINGER)); #ifdef _WHATTHEHELL_NETWORK_20060519 int nFlag; int ret = setsockopt(listen_socket_, SOL_SOCKET, SO_REUSEADDR, (char*)&nFlag, sizeof(nFlag)); #endif // set a network address ZeroMemory(&sockaddr_in_, sizeof(sockaddr_in_)); sockaddr_in_.sin_family = AF_INET; sockaddr_in_.sin_addr.s_addr = (ip_string == NULL || strlen(ip_string) == 0) ? htonl(INADDR_ANY) : inet_addr(ip_string); sockaddr_in_.sin_port = htons(port); // bind int err = ::bind(listen_socket_, (SOCKADDR *)&sockaddr_in_, sizeof(sockaddr_in_)); if (err == SOCKET_ERROR) { ::closesocket(listen_socket_); return false; } // listen err = ::listen(listen_socket_, SOMAXCONN); if (err == SOCKET_ERROR) { ::closesocket(listen_socket_); return false; } return true; } //================================================================================================== /** @remarks ¸®½¼ ¾²·¹µå¸¦ Àá½Ã ¸ØÃá´Ù. */ //================================================================================================== void Acceptor::SuspendListenThread() { for (DWORD i = 0; i < number_of_threads_; ++i) { assert(thread_handles_[i] != INVALID_HANDLE_VALUE); SuspendThread(thread_handles_[i]); } } //================================================================================================== /** @remarks ¸®½¼ ¾²·¹µå¸¦ ´Ù½Ã ±¸µ¿½ÃŲ´Ù. */ //================================================================================================== void Acceptor::ResumeListenThread() { for (DWORD i = 0; i < number_of_threads_; ++i) { assert(thread_handles_ != INVALID_HANDLE_VALUE); ResumeThread(thread_handles_[i]); } } //================================================================================================== /** @remarks ¸®½¼ ¾²·¹µå¸¦ Á¾·á½ÃŲ´Ù. */ //================================================================================================== void Acceptor::Shutdown() { // ¸ØÃç ÀÖÀ¸¸é ´Ù½Ã ±¸µ¿½ÃŲ´Ù. ResumeListenThread(); // ¸®½¼ ¼ÒÄÏ Á¾·á if (listen_socket_ != INVALID_SOCKET) { ::closesocket(listen_socket_); listen_socket_ = INVALID_SOCKET; } // acceptor ¾²·¹µå Á¾·á for (DWORD i = 0; i < number_of_threads_; ++i) { PostQueuedCompletionStatus(iocp_handle_, 0, 0, NULL); } // ¸ðµç ¿öÄ¿ ¾²·¹µå°¡ Á¾·áµÉ ¶§±îÁö ±â´Ù¸°´Ù. WaitForMultipleObjects(number_of_threads_, thread_handles_, true, INFINITE); }