#include <MSWSock.h> const int NET_BUFFER_SIZE = 1024; char tAcceptRecvBuf[NET_BUFFER_SIZE] = { 0 }; LPFN_ACCEPTEX extract_AcceptEx(); LPFN_GETACCEPTEXSOCKADDRS extract_GetAcceptExSockaddrs(); unsigned int post_accept() unsigned int __stdcall accept_callback( PTP_CALLBACK_INSTANCE Instance, PVOID pvContext, PVOID pOverlapped, ULONG IoResult, ULONG_PTR NumberOfBytesTransferred, PTP_IO pIo); LPFN_ACCEPTEX extract_AcceptEx() { LPFN_ACCEPTEX lpfnAcceptEx = NULL; GUID tGuidAcceptEx = WSAID_ACCEPTEX; DWORD dwBytes = 0; int tResult = 0; tResult = WSAIoctl( listen_socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &tGuidAcceptEx, sizeof(tGuidAcceptEx), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &dwBytes, NULL, NULL); if (SOCKET_ERROR == tResult) { return nullptr; } return lpfnAcceptEx; } LPFN_GETACCEPTEXSOCKADDRS extract_GetAcceptExSockaddrs() { LPFN_GETACCEPTEXSOCKADDRS lpfnGetAcceptExSockaddrs = NULL; GUID tGuidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS; DWORD dwBytes = 0; int tResult = 0; tResult = WSAIoctl( listen_socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &tGuidGetAcceptExSockaddrs, sizeof(tGuidGetAcceptExSockaddrs), &lpfnGetAcceptExSockaddrs, sizeof(lpfnGetAcceptExSockaddrs), &dwBytes, NULL, NULL); if (SOCKET_ERROR == tResult) { return nullptr; } return lpfnGetAcceptExSockaddrs; } unsigned int post_accept() { LPFN_ACCEPTEX lpfnAcceptEx = extract_AcceptEx(); DWORD dwBytes = 0; int tResult = 0; if (nullptr == lpfnAcceptEx) { return false; } BOOL tRtn = FALSE; overlapex *overlap = new overlapex(); overlap->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == overlap->sock) { WSACleanup(); return false; } /* 特别要注意,当dwReceiveDataLength设置为0后, 在使用m_lpfnGetAcceptExSockaddrs方法取得客户端地址时, dwReceiveDataLength也要相应的写为0, 否则取出的地址为0.0.0.0 */ tRtn = lpfnAcceptEx( listen_socket, overlap->sock, tAcceptRecvBuf, 0, // 表示只接收连接,不接收数据 sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, &dwBytes, (LPOVERLAPPED)overlap); int tErrorCode = WSAGetLastError(); if ((FALSE == tRtn) && (ERROR_IO_PENDING != tErrorCode)) { WSACleanup(); return false; } return true; } unsigned int __stdcall accept_callback( PTP_CALLBACK_INSTANCE Instance, PVOID pvContext, PVOID pOverlapped, ULONG IoResult, ULONG_PTR NumberOfBytesTransferred, PTP_IO pIo) { overlapex *overlap = static_cast<overlapex*>(pOverlapped); if (NO_ERROR != IoResult) { if (WSAENOTSOCK != IoResult) { printf("serious error in base_recv_callback(...) !!! IoResult return:%d. query System Error Code.", IoResult); } return 0; } struct sockaddr_in *local_addr = NULL; struct sockaddr_in *remote_addr = NULL; int local_addr_len = sizeof(sockaddr_in); int remote_addr_len = sizeof(sockaddr_in); LPFN_GETACCEPTEXSOCKADDRS GetAcceptExSockaddrs = extract_GetAcceptExSockaddrs(); GetAcceptExSockaddrs( tAcceptRecvBuf, 0, sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, (struct sockaddr**)&local_addr, &local_addr_len, (struct sockaddr**)&remote_addr, &remote_addr_len); /* 如果不是使用的AcceptEx这个函数, 而是使用的同步函数的话, 应该使用getpeername() & gethostname() 来获取远程机和本机的IP与PORT */ printf("对方 IP & PORT: %s %d \n", inet_ntoa(local_addr->sin_addr), ntohs(local_addr->sin_port)); printf("本机 IP & PORT: %s %d \n", inet_ntoa(remote_addr->sin_addr), ntohs(remote_addr->sin_port)); post_recv(overlap); post_accept(); return 1; }
AcceptEx 以及 获取远程IP与port,布布扣,bubuko.com
原文地址:http://www.cnblogs.com/emyueguang/p/3820823.html