bool_t AsyncAcceptor::GetPeerInfomation(char_t *buffer, uint32_t size, AsyncSession *sess) { bool_t ret = FALSE; #ifdef OS_WINDOWS sockaddr_in *local_addr = 0; sockaddr_in *remote_addr = 0; int32_t local_addr_len = 0; int32_t remote_addr_len = 0; GetAcceptExSockaddrs(buffer, 0, sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, (sockaddr **)&local_addr, &local_addr_len, (sockaddr **)&remote_addr, &remote_addr_len); Socket *sock = (Socket *)sess->Handle(); if(!sock) { ECILA_TRACE(); return FALSE; } IPAddrs *ipaddr = sock->GetIpAddrs(); if(!ipaddr) { ECILA_TRACE(); return FALSE; } ret = ipaddr->Init(remote_addr); if(!ret) { ECILA_TRACE(); return FALSE; } #endif return TRUE; }
ConnectionPtr SocketConnection::acceptSync() { LB_TS_THREAD( _recvThread ); if( !isListening( )) return 0; LBASSERT( _overlappedAcceptData ); LBASSERT( _overlappedSocket != INVALID_SOCKET ); if( _overlappedSocket == INVALID_SOCKET ) return 0; // complete accept DWORD got = 0; DWORD flags = 0; if( !WSAGetOverlappedResult( _readFD, &_overlappedRead, &got, TRUE, &flags )) { LBWARN << "Accept completion failed: " << lunchbox::sysError << ", closing socket" << std::endl; close(); return 0; } sockaddr_in* local = 0; sockaddr_in* remote = 0; int localLen = 0; int remoteLen = 0; GetAcceptExSockaddrs( _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16, sizeof( sockaddr_in ) + 16, (sockaddr**)&local, &localLen, (sockaddr**)&remote, &remoteLen ); _tuneSocket( _overlappedSocket ); ConstConnectionDescriptionPtr description = getDescription(); SocketConnection* newConnection = new SocketConnection; ConnectionPtr connection( newConnection ); // to keep ref-counting correct newConnection->_readFD = _overlappedSocket; newConnection->_writeFD = _overlappedSocket; #ifndef _WIN32 //fcntl( _overlappedSocket, F_SETFL, O_NONBLOCK ); #endif newConnection->_initAIORead(); _overlappedSocket = INVALID_SOCKET; newConnection->_setState( STATE_CONNECTED ); ConnectionDescriptionPtr newDescription = newConnection->_getDescription(); newDescription->bandwidth = description->bandwidth; newDescription->port = ntohs( remote->sin_port ); newDescription->setHostname( getHostName( *remote )); LBDEBUG << "accepted connection from " << newDescription->getHostname() << ":" << newDescription->port << std::endl; return connection; }
/* * Process the socket when the overlapped accept() completed. */ static void ioqueue_on_accept_complete(pj_ioqueue_key_t *key, ioqueue_accept_rec *accept_overlapped) { struct sockaddr *local; struct sockaddr *remote; int locallen, remotelen; pj_status_t status; PJ_CHECK_STACK(); /* On WinXP or later, use SO_UPDATE_ACCEPT_CONTEXT so that socket * addresses can be obtained with getsockname() and getpeername(). */ status = setsockopt(accept_overlapped->newsock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&key->hnd, sizeof(SOCKET)); /* SO_UPDATE_ACCEPT_CONTEXT is for WinXP or later. * So ignore the error status. */ /* Operation complete immediately. */ if (accept_overlapped->addrlen) { GetAcceptExSockaddrs( accept_overlapped->accept_buf, 0, ACCEPT_ADDR_LEN, ACCEPT_ADDR_LEN, &local, &locallen, &remote, &remotelen); if (*accept_overlapped->addrlen >= locallen) { if (accept_overlapped->local) pj_memcpy(accept_overlapped->local, local, locallen); if (accept_overlapped->remote) pj_memcpy(accept_overlapped->remote, remote, locallen); } else { if (accept_overlapped->local) pj_bzero(accept_overlapped->local, *accept_overlapped->addrlen); if (accept_overlapped->remote) pj_bzero(accept_overlapped->remote, *accept_overlapped->addrlen); } *accept_overlapped->addrlen = locallen; } if (accept_overlapped->newsock_ptr) *accept_overlapped->newsock_ptr = accept_overlapped->newsock; accept_overlapped->operation = 0; }
ConnectionPtr PGMConnection::acceptSync() { EQ_TS_THREAD( _recvThread ); if( _state != STATE_LISTENING ) return 0; EQASSERT( _overlappedAcceptData ); EQASSERT( _overlappedSocket != INVALID_SOCKET ); if( _overlappedSocket == INVALID_SOCKET ) return 0; // complete accept DWORD got = 0; DWORD flags = 0; if( !WSAGetOverlappedResult( _readFD, &_overlapped, &got, TRUE, &flags )) { EQWARN << "Accept completion failed: " << base::sysError << ", closing connection" << std::endl; close(); return 0; } sockaddr_in* local = 0; sockaddr_in* remote = 0; int localLen = 0; int remoteLen = 0; GetAcceptExSockaddrs( _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16, sizeof( sockaddr_in ) + 16, (sockaddr**)&local, &localLen, (sockaddr**)&remote, &remoteLen ); PGMConnection* newConnection = new PGMConnection; ConnectionPtr connection( newConnection ); // to keep ref-counting correct newConnection->_readFD = _overlappedSocket; _overlappedSocket = INVALID_SOCKET; newConnection->_setupReadSocket(); newConnection->_writeFD = _writeFD; newConnection->_initAIORead(); newConnection->_state = STATE_CONNECTED; newConnection->_description = _description; EQINFO << "accepted connection " << (void*)newConnection << " from " << inet_ntoa( remote->sin_addr ) << ":" << ntohs( remote->sin_port ) << std::endl; return connection; }
void IOCPConnection::OnConnect( void* pBuf ) { struct sockaddr_in* pMyAddr = NULL; struct sockaddr_in* pPeerAddr = NULL; int myLen, peerLen; GetAcceptExSockaddrs( pBuf, 0, sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, reinterpret_cast<sockaddr**>(&pMyAddr), &myLen, reinterpret_cast<sockaddr**>(&pPeerAddr), &peerLen ); m_myAddr.SetAddr( inet_ntoa(pMyAddr->sin_addr) ); m_myAddr.SetPort( ntohs(pMyAddr->sin_port) ); m_peerAddr.SetAddr( inet_ntoa(pPeerAddr->sin_addr) ); m_peerAddr.SetPort( ntohs(pPeerAddr->sin_port) ); m_bConnected = true; }
//클라이언트의ㅡaccept를 담당할 쓰레드 UINT AcceptThread( LPVOID lParam ){ SERVER_INFO* serverInfo = (SERVER_INFO*)lParam; OVERLAPPED ov; while(TRUE) { //SOCKET clientSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//이렇게 프로토콜만 결정된상태 SOCKET clientSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); char temp[1024]; DWORD dwRecv; //이건사실안나온다. 억셉트ex는 비동기함수라 바로 밑으로 빠져나간다. 그래서 dwRecv에 값이 들어갈수가없다. 형식적인거. memset(&ov, 0, sizeof(ov)); AcceptEx(*serverInfo->hServSock, clientSocket, temp, 0, sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, &dwRecv, &ov); //첫번째 listensocket, 서버소켓만들고바인드하고리슨까지한거,그다음은 acceptsocket //그럼 이제 시스템이 내부적으로 클라이언트가 connect할때까지 기다린다. //우리는 클라이언트가 커넥트하면 clientSocket가지고 링크드리스트에 집어넣고 이런작업해야한다. //근데 얘는 언제끝날지 모른다. 그래서 WaitForSingleObject((HANDLE)*serverInfo->hServSock, INFINITE); //이렇게 클라이언트가 connect할때까지 기다리는거다. //SOCKADDR_IN의 더블포인터가 필요하다. SOCKADDR_IN * pLocal; SOCKADDR_IN * pAddr; int iLocalLen = sizeof(SOCKADDR_IN); int iRemoteLen = sizeof(SOCKADDR_IN); GetAcceptExSockaddrs(temp, 0, sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, (sockaddr **)&pLocal, &iLocalLen, (sockaddr **)&pAddr, &iRemoteLen); //이 temp에 정보가 다 들어있다. CreateIoCompletionPort((HANDLE)clientSocket, *serverInfo->hComPort, (DWORD)clientSocket, 0); //세번째 파라미터가 RecvFunc에 dwCompKey로 간다. //이렇게 하면 소켓이 아까 만든 껍데기에 등록이 된다. 처음에 한명이 접근해서 하나가 등록이 된다. EnterCriticalSection(&myCS2); //client 등록 serverInfo->mCToonVasServerDlg->AddClient(clientSocket, *pAddr); LeaveCriticalSection(&myCS2); } return 0; }
bool CClient::PostConnect(NetData* pData) { CLock lock(&m_criticalSection); m_status = NETSTATUS_Connected; SOCKADDR* localAddr = NULL; SOCKADDR* remoteAddr = NULL; int localAddrLen = 0; int remoteAddrLen = 0; GetAcceptExSockaddrs(pData->buffer.buf, 0, sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, &localAddr, &localAddrLen, &remoteAddr, &remoteAddrLen); SOCKET listenSocket = m_pServer->GetListenSocket(); if (setsockopt(m_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (const char*)&listenSocket, sizeof(listenSocket)) == SOCKET_ERROR) { LOGNET("Client[%d] fail to update accept context.", GetID()); return false; } if (!m_completePort) { if (CreateIoCompletionPort((HANDLE)m_socket, m_pManager->GetIOCompletePort(), (ULONG_PTR)this, 0) == NULL) { LOG("Fail to associate client[%d] socket with completion port.", GetID()); return false; } m_completePort = true; } m_send.Clean(); m_recv.Clean(); m_discon.Clean(); m_accept.Clean(); m_lastActionTime = 0; m_status = NETSTATUS_CompletionNotify; return true; }
DWORD ThreadProcess(LPVOID pParam) { ThreadInfo* pThreadInfo = (ThreadInfo*)pParam; HANDLE hIOCP = pThreadInfo->hIOCP; SOCKET sListenConn = pThreadInfo->Conn; NetMsg* pReadMsg = pThreadInfo->ReadMsg; NetMsg* pWriteMsg = pThreadInfo->WriteMsg; OverLapped* pOver = NULL; SOCKET* pConn = NULL; DWORD dwBytes; DWORD dwFlag; for (;;) { GetQueuedCompletionStatus(hIOCP, &dwBytes, (PULONG_PTR)&pConn, (LPOVERLAPPED*)&pOver, INFINITE); if (!pConn && !pOver) return 0; if ((dwBytes == 0 && (pOver->opType == OverLapped::OLOpType::EOLOT_Send || pOver->opType == OverLapped::OLOpType::EOLOT_Recv)) || (pOver->opType == OverLapped::OLOpType::EOLOT_Accept && WSAGetLastError() == WSA_OPERATION_ABORTED)) { closesocket((SOCKET)pOver->sysBuffer.len); delete pOver; } else { switch (pOver->opType) { case OverLapped::OLOpType::EOLOT_Accept: { SOCKET sAcceptConn = (SOCKET)pOver->sysBuffer.len; int iLocalAddr, iRemoteAddr, iError; LPSOCKADDR pLocalAddr; sockaddr_in* pRemoteAddr = NULL; GetAcceptExSockaddrs(pOver->sysBuffer.buf, 0, AcceptExSockAddrInLen, AcceptExSockAddrInLen, (PSOCKADDR*)&pLocalAddr, &iLocalAddr, (PSOCKADDR*)&pRemoteAddr, &iRemoteAddr); printf("new connect: %d.%d.%d.%d\n", pRemoteAddr->sin_addr.s_net, pRemoteAddr->sin_addr.s_host, pRemoteAddr->sin_addr.s_lh, pRemoteAddr->sin_addr.s_impno); // 更新连接进来的Socket,希望ClientSocket具有和ListenSocket相同的属性,对ClientSocket调用SO_UPDATE_ACCEPT_CONTEXT // git snap (00e097d): WSAEFAULT 参数4应该指针 if (setsockopt(sAcceptConn, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&sListenConn, sizeof(sListenConn)) == SOCKET_ERROR) { Log("EOLOT_Accept [%d] setsockopt Error[%d].\n", sAcceptConn, WSAGetLastError()); closesocket(sAcceptConn); delete pOver; break; } // IOCP管理连接 // 参数4:指针 if (!CreateIoCompletionPort((HANDLE)sAcceptConn, hIOCP, (DWORD_PTR)&sAcceptConn, 0)) { Log("EOLOT_Accept [%d] CreateIoCompletionPort Error [%d].\n", sAcceptConn, WSAGetLastError()); closesocket(sAcceptConn); delete pOver; break; } delete pOver; OverLapped* pRecvOver = new OverLapped; pRecvOver->opType = OverLapped::EOLOT_Recv; pRecvOver->sysBuffer.len = OverLappedBufferLen; ZeroMemory(pRecvOver->dataBuffer, OverLappedBufferLen); // 等待接受数据 // git snap(6fa835e): Error = WSAEOPNOTSUPP(10045 Operation not supported), 参数5:flag错误 DWORD dwTemp[2] = {0, 0}; int nResult = WSARecv(sAcceptConn, &pRecvOver->sysBuffer, 1, &dwTemp[0], &dwTemp[1], &pRecvOver->sysOverLapped, NULL); if (nResult == SOCKET_ERROR && ((iError = WSAGetLastError()) != ERROR_IO_PENDING)) { Log("EOLOT_Accept [%d] WSARecv Error[%d].\n", sAcceptConn, iError); closesocket(sAcceptConn); delete pRecvOver; break; } Log("EOLOT_Accept [%d] WSARecv OK.\n", sAcceptConn); // 发送第一个数据 // git snap(): Erro = OverLapped* pSendOver = new OverLapped; pSendOver->opType = OverLapped::OLOpType::EOLOT_Send; ZeroMemory(pSendOver->dataBuffer, OverLappedBufferLen); GetSendMsg(pSendOver->dataBuffer, pSendOver->sysBuffer.len); //sprintf_s(pSendOver->dataBuffer, "server new send time %d", GetTickCount()); //pSendOver->sysBuffer.len = strlen(pSendOver->dataBuffer); int nResult2 = WSASend(sAcceptConn, &pSendOver->sysBuffer, 1, &dwBytes, 0, &pSendOver->sysOverLapped, 0); if (nResult2 == SOCKET_ERROR && ((iError = WSAGetLastError()) != ERROR_IO_PENDING)) { Log("EOLOT_Accept [%d] WSASend Error[%d].\n", sAcceptConn, iError); closesocket(sAcceptConn); delete pSendOver; break; } Log("EOLOT_Accept WSASend OK"); }break; // OverLapped::OLOpType::EOLOT_Accept case OverLapped::OLOpType::EOLOT_Send: { delete pOver; }break; // OverLapped::OLOpType::EOLOT_Send case OverLapped::OLOpType::EOLOT_Recv: { Log("EOLOT_Recv New Msg"); char* pData = pOver->dataBuffer; SOCKET sAcceptConn = *pConn; pReadMsg->AddNewMsg((void*)pData, (size_t)dwBytes, sAcceptConn); // 等待接受下一组数据 ZeroMemory(pOver->dataBuffer, OverLappedBufferLen); DWORD dwTemp[2] = { 0, 0 }; int nResult = WSARecv(sAcceptConn, &pOver->sysBuffer, 1, &dwTemp[0], &dwTemp[1], &pOver->sysOverLapped, 0); if (nResult == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING) { closesocket(sAcceptConn); delete pOver; break; } //// 模拟发送测试数据 //OverLapped* pSendOver = new OverLapped; //pSendOver->opType = OverLapped::OLOpType::EOLOT_Send; //ZeroMemory(pSendOver->dataBuffer, OverLappedBufferLen); //sprintf_s(pSendOver->dataBuffer, "server new send time %d", GetTickCount()); //pSendOver->sysBuffer.len = strlen(pSendOver->dataBuffer); //int nResult2 = WSASend(sAcceptConn, &pSendOver->sysBuffer, 1, &dwBytes, 0, &pSendOver->sysOverLapped, 0); //if (nResult2 == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING) //{ // closesocket(sAcceptConn); // delete pOver; // break; //} }break; // OverLapped::OLOpType::EOLOT_Recv } } } }
void gas_accept_completed (GAS_POLLER_INFO *pi, gas_client_info *accept_ci, BOOL resultOk, DWORD size) { DWORD addr_buffer_size = sizeof(struct sockaddr_in) + 16; struct sockaddr *LocalSockaddr, *RemoteSockaddr; int LocalSockaddrLen=0, RemoteSockaddrLen=0; if (resultOk) { gas_debug_message (GAS_IO, "New connection created\n"); GetAcceptExSockaddrs (gas_get_buffer_data(pi->accept_ci->rb), 0, addr_buffer_size, addr_buffer_size, &LocalSockaddr, &LocalSockaddrLen, &RemoteSockaddr, &RemoteSockaddrLen); if (pi->networks_info != NULL) { char address_string[30]; if (!gas_validate_network (pi, RemoteSockaddr, address_string)) { gas_error_message ("Forbidden user: %s\n", address_string); closesocket(accept_ci->socket); // starts waiting for another connection request gas_start_accepting(pi); return; } } // "updates the context" (whatever that is...) setsockopt(accept_ci->socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&pi->server_socket, sizeof(pi->server_socket)); // associates new socket with completion port gas_client_info* ci = gas_create_client (pi, accept_ci->socket); struct sockaddr_in * client_addr_in; client_addr_in = (struct sockaddr_in *) &RemoteSockaddr; memcpy (&ci->remote_addr, &client_addr_in->sin_addr, sizeof(struct in_addr)); // keep client address for reference ci->remote_port = ntohs (client_addr_in->sin_port); // and remote port client_addr_in = (struct sockaddr_in *) &LocalSockaddr; memcpy (&ci->local_addr, &client_addr_in->sin_addr, sizeof(struct in_addr)); // keep server address for reference ci->local_port = ntohs (client_addr_in->sin_port); // and local port gas_do_callback (ci, GAS_CLIENT_CREATE); if (CreateIoCompletionPort((HANDLE)ci->socket, pi->cpl_port, (ULONG_PTR)ci, 0) != pi->cpl_port) { int err = WSAGetLastError(); gas_error_message ("Error %d in CreateIoCompletionPort\n", err); } else { // starts receiving from the new connection ci->overlapped = gas_create_overlapped(pi); gas_start_reading(ci); } // starts waiting for another connection request gas_start_accepting(pi); } else { // !resultOk int err = GetLastError(); gas_debug_message (GAS_IO, "Error (%d,%d) in accept, cleaning up and retrying!!!", err, (int)size); closesocket(accept_ci->socket); gas_start_accepting(pi); } }
static unsigned int __stdcall winnt_accept(void *lr_) { ap_listen_rec *lr = (ap_listen_rec *)lr_; apr_os_sock_info_t sockinfo; PCOMP_CONTEXT context = NULL; DWORD BytesRead; SOCKET nlsd; int rv, err_count = 0; #if APR_HAVE_IPV6 SOCKADDR_STORAGE ss_listen; int namelen = sizeof(ss_listen); #endif apr_os_sock_get(&nlsd, lr->sd); #if APR_HAVE_IPV6 if (getsockname(nlsd, (struct sockaddr *)&ss_listen, &namelen) == SOCKET_ERROR) { ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_netos_error(), ap_server_conf, "winnt_accept: getsockname error on listening socket, is IPv6 available?"); return 1; } #endif ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "Child %lu: Starting thread to listen on port %d.", my_pid, lr->bind_addr->port); while (!shutdown_in_progress) { if (!context) { context = mpm_get_completion_context(); if (!context) { /* Temporary resource constraint? */ Sleep(0); continue; } } /* Create and initialize the accept socket */ #if APR_HAVE_IPV6 if (context->accept_socket == INVALID_SOCKET) { context->accept_socket = socket(ss_listen.ss_family, SOCK_STREAM, IPPROTO_TCP); context->socket_family = ss_listen.ss_family; } else if (context->socket_family != ss_listen.ss_family) { closesocket(context->accept_socket); context->accept_socket = socket(ss_listen.ss_family, SOCK_STREAM, IPPROTO_TCP); context->socket_family = ss_listen.ss_family; } if (context->accept_socket == INVALID_SOCKET) { ap_log_error(APLOG_MARK,APLOG_WARNING, apr_get_netos_error(), ap_server_conf, "winnt_accept: Failed to allocate an accept socket. " "Temporary resource constraint? Try again."); Sleep(100); continue; } #else if (context->accept_socket == INVALID_SOCKET) { context->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (context->accept_socket == INVALID_SOCKET) { /* Another temporary condition? */ ap_log_error(APLOG_MARK,APLOG_WARNING, apr_get_netos_error(), ap_server_conf, "winnt_accept: Failed to allocate an accept socket. " "Temporary resource constraint? Try again."); Sleep(100); continue; } } #endif /* AcceptEx on the completion context. The completion context will be * signaled when a connection is accepted. */ if (!AcceptEx(nlsd, context->accept_socket, context->buff, 0, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE, &BytesRead, &context->Overlapped)) { rv = apr_get_netos_error(); if ((rv == APR_FROM_OS_ERROR(WSAEINVAL)) || (rv == APR_FROM_OS_ERROR(WSAENOTSOCK))) { /* We can get here when: * 1) the client disconnects early * 2) TransmitFile does not properly recycle the accept socket (typically * because the client disconnected) * 3) there is VPN or Firewall software installed with buggy AcceptEx implementation * 4) the webserver is using a dynamic address that has changed */ ++err_count; closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "Child %lu: Encountered too many errors accepting client connections. " "Possible causes: dynamic address renewal, or incompatible VPN or firewall software. " "Try using the Win32DisableAcceptEx directive.", my_pid); err_count = 0; } continue; } else if ((rv != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) && (rv != APR_FROM_OS_ERROR(WSA_IO_PENDING))) { ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK,APLOG_ERR, rv, ap_server_conf, "Child %lu: Encountered too many errors accepting client connections. " "Possible causes: Unknown. " "Try using the Win32DisableAcceptEx directive.", my_pid); err_count = 0; } closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; continue; } err_count = 0; /* Wait for pending i/o. * Wake up once per second to check for shutdown . * XXX: We should be waiting on exit_event instead of polling */ while (1) { rv = WaitForSingleObject(context->Overlapped.hEvent, 1000); if (rv == WAIT_OBJECT_0) { if (context->accept_socket == INVALID_SOCKET) { /* socket already closed */ break; } if (!GetOverlappedResult((HANDLE)context->accept_socket, &context->Overlapped, &BytesRead, FALSE)) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(), ap_server_conf, "winnt_accept: Asynchronous AcceptEx failed."); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; } break; } /* WAIT_TIMEOUT */ if (shutdown_in_progress) { closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; break; } } if (context->accept_socket == INVALID_SOCKET) { continue; } } err_count = 0; /* Inherit the listen socket settings. Required for * shutdown() to work */ if (setsockopt(context->accept_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&nlsd, sizeof(nlsd))) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed."); /* Not a failure condition. Keep running. */ } /* Get the local & remote address */ GetAcceptExSockaddrs(context->buff, 0, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE, &context->sa_server, &context->sa_server_len, &context->sa_client, &context->sa_client_len); sockinfo.os_sock = &context->accept_socket; sockinfo.local = context->sa_server; sockinfo.remote = context->sa_client; sockinfo.family = context->sa_server->sa_family; sockinfo.type = SOCK_STREAM; apr_os_sock_make(&context->sock, &sockinfo, context->ptrans); /* When a connection is received, send an io completion notification to * the ThreadDispatchIOCP. This function could be replaced by * mpm_post_completion_context(), but why do an extra function call... */ PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_CONNECTION_ACCEPTED, &context->Overlapped); context = NULL; } if (!shutdown_in_progress) { /* Yow, hit an irrecoverable error! Tell the child to die. */ SetEvent(exit_event); } ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ap_server_conf, "Child %lu: Accept thread exiting.", my_pid); return 0; }
unsigned int __stdcall CEgTcpDriver::WorkerThread(void * pThisClass) { CEgTcpDriver * pThis = (CEgTcpDriver*)pThisClass; BOOL bSuccess = FALSE; int nRet; DWORD dwIoSize; DWORD dwRes = 0; LPOVERLAPPED lpOverlapped = NULL; PPER_SOCKET_CONTEXT lpPerSocketContext = NULL; PPER_IO_CONTEXT lpIOContext = NULL; CoInitializeEx(NULL, pThis->m_ThreadingModel); while (TRUE) { // continually loop to service io completion packets bSuccess = GetQueuedCompletionStatus( pThis->m_hIocp, &dwIoSize, (PDWORD_PTR)&lpPerSocketContext, &lpOverlapped, INFINITE ); // exit condition if (lpPerSocketContext == NULL) break; lpIOContext = (PPER_IO_CONTEXT)&lpPerSocketContext->m_pIOContext; //We should never skip the loop and not post another AcceptEx if the current //completion packet is for previous AcceptEx if (lpIOContext->m_IoOperation != ClientIoAccept) { if (!bSuccess || (bSuccess && (0 == dwIoSize)) ) { #ifdef _DEBUG DWORD dwErr = GetLastError(); #endif // client connection dropped pThis->m_SocketContextsLock.Lock(); pThis->CloseClient(*lpPerSocketContext); pThis->m_SocketContextsLock.Unlock(); continue; } } switch (lpIOContext->m_IoOperation) { case ClientIoAccept: { SOCKADDR_IN *LocalSockaddr, *RemoteSockaddr; INT LocalSockaddrLength, RemoteSockaddrLength; assert(dwIoSize == 0); GetAcceptExSockaddrs( lpPerSocketContext->m_pIOContext.m_ReceiveBuffer.buf, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, (SOCKADDR**)&LocalSockaddr, &LocalSockaddrLength, (SOCKADDR**)&RemoteSockaddr, &RemoteSockaddrLength ); PER_SOCKET_CONTEXT AcceptSocketContext; AcceptSocketContext.m_ConnectioID.m_LocalAddr = *LocalSockaddr; AcceptSocketContext.m_ConnectioID.m_RemoteAddr = *RemoteSockaddr; AcceptSocketContext.m_pIOContext.m_IoOperation = ClientIoRead; AcceptSocketContext.m_ConnectioID.m_Socket = lpPerSocketContext->m_pIOContext.m_SocketAccept; pair<set<PER_SOCKET_CONTEXT>::iterator, bool> InsIt; pThis->m_SocketContextsLock.Lock(); while(true) { InsIt = pThis->m_SocketContexts.insert(AcceptSocketContext); if (InsIt.second == true) break; SwitchToThread(); } nRet = setsockopt(lpPerSocketContext->m_pIOContext.m_SocketAccept, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&(pThis->m_ListenSocket), sizeof(pThis->m_ListenSocket) ); if (nRet == SOCKET_ERROR) { #ifdef _DEBUG DWORD e = WSAGetLastError(); #endif pThis->CloseClient(AcceptSocketContext); pThis->m_SocketContextsLock.Unlock(); break; } PER_SOCKET_CONTEXT & SocketContext = *(InsIt.first); dwRes = pThis->BindCompletionPort(SocketContext); if (dwRes != 0) { pThis->CloseClient(AcceptSocketContext); pThis->m_SocketContextsLock.Unlock(); break; } // while Send method is not called we are waiting for client's data BOOL bConnectionEnabled = m_bInited ? pThis->m_pEvents->OnConnect(SocketContext.m_ConnectioID, TRUE) : FALSE; if (bConnectionEnabled) { pThis->QueueReceiveOperation(SocketContext, DEFAULT_BUFFER_SIZE); } else { pThis->CloseClient(SocketContext, CONNECTION_DISCARDED); } pThis->m_SocketContextsLock.Unlock(); // pending for another connection dwRes = pThis->CreateAcceptSocket(FALSE); } break; case ClientIoRead: case ClientIoWrite: DWORD cbTransferReceive; DWORD cbTransferSend; DWORD dwFlags; BOOL bRes; bRes = WSAGetOverlappedResult(lpPerSocketContext->m_ConnectioID.m_Socket, &lpPerSocketContext->m_pIOContext.m_SendOverlapped, &cbTransferSend,FALSE, &dwFlags); if (bRes == TRUE && cbTransferSend == dwIoSize) { } #ifdef _DEBUG if (bRes == FALSE) { DWORD dwErr = WSAGetLastError(); } #endif bRes = WSAGetOverlappedResult(lpPerSocketContext->m_ConnectioID.m_Socket, &lpPerSocketContext->m_pIOContext.m_ReceiveOverlapped, &cbTransferReceive,FALSE, &dwFlags); if (bRes == TRUE && cbTransferReceive == dwIoSize) { if (pThis->m_bInited) pThis->m_pEvents->OnReceive(lpPerSocketContext->m_ConnectioID, lpPerSocketContext->m_pIOContext.m_ReceiveBuffer.m_pData, dwIoSize); lpPerSocketContext->m_pIOContext.m_ReceiveBuffer.m_dwTransferred = 0; pThis->QueueReceiveOperation(*lpPerSocketContext, DEFAULT_BUFFER_SIZE); } #ifdef _DEBUG if (bRes == FALSE) { DWORD dwErr = WSAGetLastError(); } #endif break; } } CoUninitialize(); return(0); }
static unsigned int __stdcall winnt_accept(void *lr_) { ap_listen_rec *lr = (ap_listen_rec *)lr_; apr_os_sock_info_t sockinfo; winnt_conn_ctx_t *context = NULL; DWORD BytesRead; SOCKET nlsd; core_server_config *core_sconf; const char *accf_name; int rv; int accf; int err_count = 0; HANDLE events[3]; #if APR_HAVE_IPV6 SOCKADDR_STORAGE ss_listen; int namelen = sizeof(ss_listen); #endif u_long zero = 0; core_sconf = ap_get_core_module_config(ap_server_conf->module_config); accf_name = apr_table_get(core_sconf->accf_map, lr->protocol); if (strcmp(accf_name, "data") == 0) accf = 2; else if (strcmp(accf_name, "connect") == 0) accf = 1; else if (strcmp(accf_name, "none") == 0) accf = 0; else { accf = 0; accf_name = "none"; ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, APLOGNO(00331) "winnt_accept: unrecognized AcceptFilter '%s', " "only 'data', 'connect' or 'none' are valid. " "Using 'none' instead", accf_name); } apr_os_sock_get(&nlsd, lr->sd); #if APR_HAVE_IPV6 if (getsockname(nlsd, (struct sockaddr *)&ss_listen, &namelen) == SOCKET_ERROR) { ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), ap_server_conf, APLOGNO(00332) "winnt_accept: getsockname error on listening socket, " "is IPv6 available?"); return 1; } #endif if (accf > 0) /* 'data' or 'connect' */ { /* first, high priority event is an already accepted connection */ events[1] = exit_event; events[2] = max_requests_per_child_event; } else /* accf == 0, 'none' */ { reinit: /* target of data or connect upon too many AcceptEx failures */ /* last, low priority event is a not yet accepted connection */ events[0] = exit_event; events[1] = max_requests_per_child_event; events[2] = CreateEvent(NULL, FALSE, FALSE, NULL); /* The event needs to be removed from the accepted socket, * if not removed from the listen socket prior to accept(), */ rv = WSAEventSelect(nlsd, events[2], FD_ACCEPT); if (rv) { ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), ap_server_conf, APLOGNO(00333) "WSAEventSelect() failed."); CloseHandle(events[2]); return 1; } } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00334) "Child: Accept thread listening on %pI using AcceptFilter %s", lr->bind_addr, accf_name); while (!shutdown_in_progress) { if (!context) { int timeout; context = mpm_get_completion_context(&timeout); if (!context) { if (!timeout) { /* Hopefully a temporary condition in the provider? */ ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, APLOGNO(00335) "winnt_accept: Too many failures grabbing a " "connection ctx. Aborting."); break; } } Sleep(100); continue; } } if (accf > 0) /* Either 'connect' or 'data' */ { DWORD len; char *buf; /* Create and initialize the accept socket */ #if APR_HAVE_IPV6 if (context->accept_socket == INVALID_SOCKET) { context->accept_socket = socket(ss_listen.ss_family, SOCK_STREAM, IPPROTO_TCP); context->socket_family = ss_listen.ss_family; } else if (context->socket_family != ss_listen.ss_family) { closesocket(context->accept_socket); context->accept_socket = socket(ss_listen.ss_family, SOCK_STREAM, IPPROTO_TCP); context->socket_family = ss_listen.ss_family; } #else if (context->accept_socket == INVALID_SOCKET) context->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); #endif if (context->accept_socket == INVALID_SOCKET) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, APLOGNO(00336) "winnt_accept: Failed to allocate an accept socket. " "Temporary resource constraint? Try again."); Sleep(100); continue; } if (accf == 2) { /* 'data' */ len = APR_BUCKET_BUFF_SIZE; buf = apr_bucket_alloc(len, context->ba); len -= PADDED_ADDR_SIZE * 2; } else /* (accf == 1) 'connect' */ { len = 0; buf = context->buff; } /* AcceptEx on the completion context. The completion context will be * signaled when a connection is accepted. */ if (!AcceptEx(nlsd, context->accept_socket, buf, len, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE, &BytesRead, &context->overlapped)) { rv = apr_get_netos_error(); if ((rv == APR_FROM_OS_ERROR(WSAECONNRESET)) || (rv == APR_FROM_OS_ERROR(WSAEACCES))) { /* We can get here when: * 1) the client disconnects early * 2) handshake was incomplete */ if (accf == 2) apr_bucket_free(buf); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; continue; } else if ((rv == APR_FROM_OS_ERROR(WSAEINVAL)) || (rv == APR_FROM_OS_ERROR(WSAENOTSOCK))) { /* We can get here when: * 1) TransmitFile does not properly recycle the accept socket (typically * because the client disconnected) * 2) there is VPN or Firewall software installed with * buggy WSAAccept or WSADuplicateSocket implementation * 3) the dynamic address / adapter has changed * Give five chances, then fall back on AcceptFilter 'none' */ if (accf == 2) apr_bucket_free(buf); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00337) "Child: Encountered too many AcceptEx " "faults accepting client connections. " "Possible causes: dynamic address renewal, " "or incompatible VPN or firewall software. "); ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf, APLOGNO(00338) "winnt_mpm: falling back to " "'AcceptFilter none'."); err_count = 0; accf = 0; } continue; } else if ((rv != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) && (rv != APR_FROM_OS_ERROR(WSA_IO_PENDING))) { if (accf == 2) apr_bucket_free(buf); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00339) "Child: Encountered too many AcceptEx " "faults accepting client connections."); ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf, APLOGNO(00340) "winnt_mpm: falling back to " "'AcceptFilter none'."); err_count = 0; accf = 0; goto reinit; } continue; } err_count = 0; events[0] = context->overlapped.hEvent; do { rv = WaitForMultipleObjectsEx(3, events, FALSE, INFINITE, TRUE); } while (rv == WAIT_IO_COMPLETION); if (rv == WAIT_OBJECT_0) { if ((context->accept_socket != INVALID_SOCKET) && !GetOverlappedResult((HANDLE)context->accept_socket, &context->overlapped, &BytesRead, FALSE)) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(), ap_server_conf, APLOGNO(00341) "winnt_accept: Asynchronous AcceptEx failed."); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; } } else { /* exit_event triggered or event handle was closed */ closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; if (accf == 2) apr_bucket_free(buf); break; } if (context->accept_socket == INVALID_SOCKET) { if (accf == 2) apr_bucket_free(buf); continue; } } err_count = 0; /* Potential optimization; consider handing off to the worker */ /* Inherit the listen socket settings. Required for * shutdown() to work */ if (setsockopt(context->accept_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&nlsd, sizeof(nlsd))) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, APLOGNO(00342) "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed."); /* Not a failure condition. Keep running. */ } /* Get the local & remote address * TODO; error check */ GetAcceptExSockaddrs(buf, len, PADDED_ADDR_SIZE, PADDED_ADDR_SIZE, &context->sa_server, &context->sa_server_len, &context->sa_client, &context->sa_client_len); /* For 'data', craft a bucket for our data result * and pass to worker_main as context->overlapped.Pointer */ if (accf == 2 && BytesRead) { apr_bucket *b; b = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE, apr_bucket_free, context->ba); /* Adjust the bucket to refer to the actual bytes read */ b->length = BytesRead; context->overlapped.Pointer = b; } else context->overlapped.Pointer = NULL; } else /* (accf = 0) e.g. 'none' */ { /* There is no socket reuse without AcceptEx() */ if (context->accept_socket != INVALID_SOCKET) closesocket(context->accept_socket); /* This could be a persistent event per-listener rather than * per-accept. However, the event needs to be removed from * the target socket if not removed from the listen socket * prior to accept(), or the event select is inherited. * and must be removed from the accepted socket. */ do { rv = WaitForMultipleObjectsEx(3, events, FALSE, INFINITE, TRUE); } while (rv == WAIT_IO_COMPLETION); if (rv != WAIT_OBJECT_0 + 2) { /* not FD_ACCEPT; * exit_event triggered or event handle was closed */ break; } context->sa_server = (void *) context->buff; context->sa_server_len = sizeof(context->buff) / 2; context->sa_client_len = context->sa_server_len; context->sa_client = (void *) (context->buff + context->sa_server_len); context->accept_socket = accept(nlsd, context->sa_server, &context->sa_server_len); if (context->accept_socket == INVALID_SOCKET) { rv = apr_get_netos_error(); if ( rv == APR_FROM_OS_ERROR(WSAECONNRESET) || rv == APR_FROM_OS_ERROR(WSAEINPROGRESS) || rv == APR_FROM_OS_ERROR(WSAEWOULDBLOCK) ) { ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(00343) "accept() failed, retrying."); continue; } /* A more serious error than 'retry', log it */ ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00344) "accept() failed."); if ( rv == APR_FROM_OS_ERROR(WSAEMFILE) || rv == APR_FROM_OS_ERROR(WSAENOBUFS) ) { /* Hopefully a temporary condition in the provider? */ Sleep(100); ++err_count; if (err_count > MAX_ACCEPTEX_ERR_COUNT) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00345) "Child: Encountered too many accept() " "resource faults, aborting."); break; } continue; } break; } /* Per MSDN, cancel the inherited association of this socket * to the WSAEventSelect API, and restore the state corresponding * to apr_os_sock_make's default assumptions (really, a flaw within * os_sock_make and os_sock_put that it does not query). */ WSAEventSelect(context->accept_socket, 0, 0); context->overlapped.Pointer = NULL; err_count = 0; context->sa_server_len = sizeof(context->buff) / 2; if (getsockname(context->accept_socket, context->sa_server, &context->sa_server_len) == SOCKET_ERROR) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, APLOGNO(00346) "getsockname failed"); continue; } if ((getpeername(context->accept_socket, context->sa_client, &context->sa_client_len)) == SOCKET_ERROR) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, APLOGNO(00347) "getpeername failed"); memset(&context->sa_client, '\0', sizeof(context->sa_client)); } } sockinfo.os_sock = &context->accept_socket; sockinfo.local = context->sa_server; sockinfo.remote = context->sa_client; sockinfo.family = context->sa_server->sa_family; sockinfo.type = SOCK_STREAM; sockinfo.protocol = IPPROTO_TCP; /* Restore the state corresponding to apr_os_sock_make's default * assumption of timeout -1 (really, a flaw of os_sock_make and * os_sock_put that it does not query to determine ->timeout). * XXX: Upon a fix to APR, these three statements should disappear. */ ioctlsocket(context->accept_socket, FIONBIO, &zero); setsockopt(context->accept_socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &zero, sizeof(zero)); setsockopt(context->accept_socket, SOL_SOCKET, SO_SNDTIMEO, (char *) &zero, sizeof(zero)); apr_os_sock_make(&context->sock, &sockinfo, context->ptrans); /* When a connection is received, send an io completion notification * to the ThreadDispatchIOCP. */ PostQueuedCompletionStatus(ThreadDispatchIOCP, BytesRead, IOCP_CONNECTION_ACCEPTED, &context->overlapped); context = NULL; } if (!accf) CloseHandle(events[2]); if (!shutdown_in_progress) { /* Yow, hit an irrecoverable error! Tell the child to die. */ SetEvent(exit_event); } ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ap_server_conf, APLOGNO(00348) "Child: Accept thread exiting."); return 0; }
int socket_accept4(int s,char *ip,uint16 *port) { struct sockaddr_in si; socklen_t len = sizeof si; int fd; #ifdef __MINGW32__ io_entry* e=array_get(&io_fds,sizeof(io_entry),s); if (e && e->inuse) { int sa2len; fd=-1; if (e->acceptqueued==1) { errno=EAGAIN; return -1; } if (e->acceptqueued==2) { incoming: /* incoming! */ { struct sockaddr* x,* y; GetAcceptExSockaddrs(e->inbuf,0,200,200,&x,&sa2len,&y,&len); if (len>sizeof(si)) len=sizeof(si); memcpy(&si,y,len); } fd=e->next_accept; e->next_accept=0; if (e->nonblock) { if (io_fd(fd)) { io_entry* f=array_get(&io_fds,sizeof(io_entry),fd); if (f) { f->nonblock=1; /* printf("setting fd %lu to non-blocking\n",(int)fd);*/ } } } } /* no accept queued, queue one now. */ if (e->next_accept==0) { e->next_accept=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (e==-1) return winsock2errno(-1); } if (AcceptEx(s,e->next_accept,e->inbuf,0,200,200,&e->errorcode,&e->or)) goto incoming; if (WSAGetLastError() != ERROR_IO_PENDING) return winsock2errno(-1); e->acceptqueued=1; if (fd==-1) { errno=EAGAIN; return fd; } } else { #endif if ((fd=accept(s,(void*) &si,&len))==-1) return winsock2errno(-1); #ifdef __MINGW32__ } #endif if (ip) *(uint32*)ip = *(uint32*)&si.sin_addr; if (port) uint16_unpack_big((char *) &si.sin_port,port); return fd; }
bool CServerSocket::AcceptCompleted( CSocketBuffer * pBuffer, DWORD dwReceiveByte ) { bool bRet ; // Accept 가 완료되면. if( pBuffer && pBuffer->IsConnected() ) { pool_lock() ; try{ pBuffer->m_bAccepted = true ; } catch (...) { ::PrintConsole("[exception] %s, %d \n", __FILE__, __LINE__ ) ; } pool_unlock() ; ::InterlockedDecrement( &m_nCurPendingAccept ) ; //SetEvent( m_hAcceptPostEvent ) ; int nEstablishedSeconds = 0; int bytes = sizeof(nEstablishedSeconds); int err = ::getsockopt(pBuffer->socket, SOL_SOCKET, SO_CONNECT_TIME, (char*)&nEstablishedSeconds, &bytes); if (nEstablishedSeconds == 0xffffffff) { // 현재 연결되지 않은 넘 ::PrintConsole( "[ERROR] Dissconnected socket \n") ; return false ; } else { // nEstablishedSeconds --> 커넥션 이루어진 때로부터 현재까지 경과한 초단위 시간 } if( SOCKET_ERROR == ::setsockopt( pBuffer->socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&m_listensocket, sizeof(m_listensocket) ) ) { ::PrintConsole( "CServerSocket::AcceptCompleted setsockopt failed - Code %d\n", ::WSAGetLastError() ) ; } // 주소를 채우고, // int sizeofLocal=0, sizeofRemote = 0 ; SOCKADDR * pLocal = NULL, * pRemote = NULL ; GetAcceptExSockaddrs( pBuffer->m_buf, 0, m_sizeofaddr, m_sizeofaddr, &pLocal, &sizeofLocal, &pRemote, &sizeofRemote ) ; if( pRemote ) { ::CopyMemory( &pBuffer->addr, pRemote, sizeof(SOCKADDR) ) ; //printf( "Ip = %s\n", inet_ntoa( pBuffer->addr.sin_addr ) ) ; } tcp_keepalive keepAlive, outKeepAlive = {0}; DWORD outByte ; keepAlive.onoff = 1 ; keepAlive.keepaliveinterval = _KEEPALIVE_INTERVAL_ ; keepAlive.keepalivetime = _KEEPALIVE_TIME_ ; WSAIoctl( pBuffer->socket, SIO_KEEPALIVE_VALS, &keepAlive, sizeof(keepAlive), &outKeepAlive, sizeof(outKeepAlive), &outByte, NULL, NULL ) ; // completion port 와 연결한다.. /* if( m_iocp.AssociateSocket( pBuffer ) == false ) { int iError = WSAGetLastError() ; ::PrintConsole( " m_iocp.AssociateSocket( pBuf ) == false (err_code :%d)\n", iError ) ; } */ //OnConnectionEstablished( pBuffer ) ; bRet = true ; } else { ::PrintConsole("[ERROR] if( pBuffer && pBuffer->IsConnected() == false ) \n" ) ; bRet = false ; } return bRet ; }