//--------------------------------------------------------------------------------------------------------------------------- //PostAccept() //--------------------------------------------------------------------------------------------------------------------------- int CIocpServer::PostAccept(SOCKET_OBJ *sock, BUFFER_OBJ *acceptobj) { DWORD bytes; int rc; acceptobj->operation = OP_ACCEPT; LOCK(&sock->cs); acceptobj->sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (acceptobj->sclient == INVALID_SOCKET) { #ifdef LOG_LEVEL2 Log_Server.Write("PostAccept(socket())错误: %d",WSAGetLastError()); #endif rc = -1; } else { rc = lpfnAcceptEx( sock->s, acceptobj->sclient, acceptobj->buf, 0, //acceptobj->buflen - ((sizeof(SOCKADDR_STORAGE) + 16) * 2), //把缓冲大小设置为0,可以使Accept接收到连接就立即返回。 sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16, &bytes, &acceptobj->ol ); if (rc == FALSE && WSAGetLastError() != WSA_IO_PENDING) { #ifdef LOG_LEVEL2 Log_Server.Write("(->%d)PostAccept错误: %d",sock->s,WSAGetLastError()); #endif closesocket(acceptobj->sclient); acceptobj->sclient = INVALID_SOCKET; } else { #ifdef LOG_STATUS InterlockedIncrement(&gIoCount); #endif InterlockedIncrement(&m_accept_count); rc = 0; } } UNLOCK(&sock->cs); return rc; }
// main thread and socket threads int ServerSocket::postAcceptEx() { SOCKET acceptSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED); OverlappedData* ioData = createOverlappedData(ACCEPT, BUFFER_SIZE, acceptSocket); DWORD dwBytes = 0; int result = lpfnAcceptEx(listenSocket, acceptSocket, ioData->buffer, 0, ADDRESS_LENGTH, ADDRESS_LENGTH, &dwBytes, &(ioData->overlapped)); if (result == FALSE && WSAGetLastError() != ERROR_IO_PENDING) { Log::e("lpfnAcceptEx error.. %d", WSAGetLastError()); return -1; } return 0; }
int api_tcp_accept(api_tcp_listener_t* listener, api_tcp_t* tcp) { api_tcp_listener_accept_t accept; CHAR buffer[2 * (sizeof(SOCKADDR_IN) + 16)]; SOCKADDR *lpLocalSockaddr = NULL; SOCKADDR *lpRemoteSockaddr = NULL; int localSockaddrLen = 0; int remoteSockaddrLen = 0; DWORD dwBytes; BOOL result; BOOL success = FALSE; BOOL completed = FALSE; DWORD sys_error; int error = API__OK; memset(&listener->os_win.ovl, 0, sizeof(listener->os_win.ovl)); if (listener->loop->terminated) return API__TERMINATE; if (listener->status.closed || listener->status.terminated || listener->status.error != API__OK) return listener->status.error; accept.task = listener->loop->scheduler.current; listener->os_win.reserved = &accept; do { success = FALSE; completed = FALSE; tcp->stream.fd = WSASocket(listener->os_win.af, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); result = lpfnAcceptEx(listener->fd, tcp->stream.fd, buffer, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &dwBytes, (LPOVERLAPPED)&listener->os_win.ovl); if (!result) { sys_error = WSAGetLastError(); if (sys_error == ERROR_SUCCESS) { completed = TRUE; } else if (sys_error != WSA_IO_PENDING) { listener->status.error = api_error_translate(sys_error); closesocket(tcp->stream.fd); break; } } else { completed = TRUE; } if (!completed) api_task_sleep(accept.task); lpfnGetAcceptExSockaddrs(buffer, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &lpLocalSockaddr, &localSockaddrLen, &lpRemoteSockaddr, &remoteSockaddrLen); tcp->address.length = remoteSockaddrLen; memcpy(&tcp->address.address, lpRemoteSockaddr, remoteSockaddrLen); success = listener->on_accept(listener, tcp); if (success) { error = api_socket_non_block(tcp->stream.fd, 1); error = api_socket_recv_buffer_size(tcp->stream.fd, 0); error = api_socket_send_buffer_size(tcp->stream.fd, 0); error = api_tcp_nodelay(tcp->stream.fd, 1); api_stream_init(&tcp->stream, STREAM_Tcp, tcp->stream.fd); } else { closesocket(tcp->stream.fd); } } while (!success); listener->os_win.reserved = 0; if (success) return API__OK; return listener->status.error; }