// 创建 Listen Socket,进入监听状态,等待客户端的连接 bool CServer::Host(UINT dwPort, const char* strIP,long lFlag, ulong nSocketType) { if(!(m_bMode&2)) return FALSE; SetFlag(lFlag); // 创建 socket bool bRet = CreateEx(dwPort, strIP,nSocketType); //创建失败 if(!bRet) { return bRet; } //创建接收客户socket线程 bRet=CreateAcceptThread(); if(!bRet) { PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"创建接受连接线程失败!"); return FALSE; } // listen bRet = Listen(m_lMaxBlockConnetNum); if(!bRet) { PutErrorString(NET_MODULE,"%-15s %s",__FUNCTION__,"listen 失败!"); return FALSE; } return bRet; }
BOOL CIOCPort::Listen(int port) { int opt; struct sockaddr_in addr; struct linger lingerOpt; // Open a TCP socket (an Internet stream socket). // if ( ( m_ListenSocket = socket(AF_INET, SOCK_STREAM, 0) ) < 0 ) { TRACE("Can't open stream socket\n"); return FALSE; } // Bind our local address so that the client can send to us. // memset((void *)&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); // added in an attempt to allow rebinding to the port // opt = 1; setsockopt( m_ListenSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); opt = 1; setsockopt( m_ListenSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, sizeof(opt)); // Linger off -> close socket immediately regardless of existance of data // lingerOpt.l_onoff = 1; lingerOpt.l_linger = 0; setsockopt(m_ListenSocket, SOL_SOCKET, SO_LINGER, (char *)&lingerOpt, sizeof(lingerOpt)); if ( bind(m_ListenSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0 ) { TRACE("Can't bind local address\n"); return FALSE; } int socklen, len, err; socklen = SOCKET_BUFF_SIZE*4; setsockopt( m_ListenSocket, SOL_SOCKET, SO_RCVBUF, (char*)&socklen, sizeof(socklen)); len = sizeof(socklen); err = getsockopt( m_ListenSocket, SOL_SOCKET, SO_RCVBUF, (char*)&socklen, &len); if (err == SOCKET_ERROR) { TRACE("FAIL : Set Socket RecvBuf of port(%d) as %d\n", port, socklen); return FALSE; } socklen = SOCKET_BUFF_SIZE*4; setsockopt( m_ListenSocket, SOL_SOCKET, SO_SNDBUF, (char*)&socklen, sizeof(socklen)); len = sizeof(socklen); err = getsockopt( m_ListenSocket, SOL_SOCKET, SO_SNDBUF, (char*)&socklen, &len); if (err == SOCKET_ERROR) { TRACE("FAIL: Set Socket SendBuf of port(%d) as %d\n", port, socklen); return FALSE; } listen(m_ListenSocket, 5); m_hListenEvent = WSACreateEvent(); if( m_hListenEvent == WSA_INVALID_EVENT ) { err = WSAGetLastError(); TRACE("Listen Event Create Fail!! %d \n", err); return FALSE; } WSAEventSelect( m_ListenSocket, m_hListenEvent, FD_ACCEPT); TRACE("Port (%05d) initialzed\n", port); CreateAcceptThread(); return TRUE; }
/** @brief @param numWorkThread 0이면 시스템 코어에 맞춰 자동 */ void XEWinSocketSvr::Create( WORD port, int numWorkThread ) { XBREAK( port == 0 ); if( XWinNetwork::sStartUp() == false ) { XALERT( "WSAStartup failed" ); return; } // // m_Socket = socket( AF_INET, SOCK_STREAM, 0 ); m_Socket = WSASocket( PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED ); if( m_Socket == INVALID_SOCKET ) { XALERT( "create socket failed" ); return; } SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_port = htons( port ); addr.sin_addr.S_un.S_addr = htonl( INADDR_ANY ); if( bind( m_Socket, ( struct sockaddr * )&addr, sizeof( addr ) ) == SOCKET_ERROR ) { XBREAK(1); XALERT( "Network bind error" ); Destroy(); return; } // m_Port = port; // 클라로부터 접속을 받을 준비 if( listen( m_Socket, SOMAXCONN ) == SOCKET_ERROR ) { XALERT( "Network::listen error" ); Destroy(); return; } // m_pUserMng = CreateUserMng( m_maxConnect ); XBREAK( m_pUserMng == NULL ); // 유저 커스텀 create OnCreate(); // virtual // IOCP 객체 생성 m_hIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 ); // 워커 스레드 생성 SYSTEM_INFO si; memset( &si, 0, sizeof(si)); GetSystemInfo( &si ); #if defined(_DEBUG) && !defined(_XBOT) const int numThread = 4; // 개발중엔 편의상 스레드 적게쓴다. #else const int numThread = (numWorkThread == 0)? (int)(si.dwNumberOfProcessors * 2) : numWorkThread; #endif XBREAK( numThread <= 0 || numThread > 32 ); for( int i = 0; i < numThread; ++i ) { m_aryThreadWork.push_back( CreateWorkThread() ); } // accept( 클라이언트로부터의 접속대기 ) 스레드 생성 m_thAccept = CreateAcceptThread(); // #if _DEV_LEVEL <= DLV_OPEN_BETA m_timerSec.Set( 1.f ); #endif }