大家好,又见面了,我是你们的朋友全栈君。
AcceptEx函数的定义如下:
BOOL AcceptEx (
SOCKET
sListenSocket, SOCKET
sAcceptSocket, PVOID
lpOutputBuffer, DWORD
dwReceiveDataLength, DWORD
dwLocalAddressLength, DWORD
dwRemoteAddressLength, LPDWORD
lpdwBytesReceived, LPOVERLAPPED
lpOverlapped );
参数1–sListenSocket, accept前绑定到本地地址的监听socket,一般由listen()得到
参数2–sAcceptSocket, 用于接受连接的socket,本人理解应该更主要是的一个out参数。
参数3–lpOutputBuffer,一块内存,当Accept成功时,会有本地(server)的地址信息,
远端地址信息(client),可能还有数据(当dwReceiveDataLength!=0时)将得到。此参数将存放这
3种信息,其中,它们是这样存放的:开始dwReceiveDataLength个大小,用于存放Accept时接到
到的数据,后面接着存放server的地址,接着是client的地址信息。该参数比较重要,如果使用
不当,可能会引起内存溢出。
参数4–dwReceiveDataLength,lpOutputBuffer中用于存放数据的空间大小。如果此参数=0,则Accept时
将不会待数据到来,而直接返回,所以通常当Accept有数据时,该参数设成为:
sizeof(lpOutputBuffer)(实参的实际空间大小) – 2*(sizeof
sockaddr_in 16)。
参数5–dwLocalAddressLength,存放本地址地址信息的空间大小
参数6–dwRemoteAddressLength,存放本远端地址信息的空间大小
参数7–lpdwBytesReceived,out参数,用于存放接收到的数据长度。该参数只是在同步IO的时候会有效
返回,如果是异步的重叠IO,需从完成通知信息里面得到。(详见MSDN)
参数8–lpOverlapped,标识异步操作时的重叠IO结构信息。
使用此函数时,要包含头文:Mswsock.h,同时要链接:Mswsock.lib。可在源程序中加入下面的语句,这样在编译时,将自动链接Mswsock.lib。
#pragma comment(lib,” Mswsock.lib”)
下面是使用AcceptEx函数的示例代码:
#define STRICT
#define _WIN32_WINNT 0x0500 // Windows 2000 or later
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
#pragma comment(lib,”Ws2_32.lib”)
#pragma comment(lib,”Mswsock.lib”)
int main()
{
const int BUFSIZE = 48;
LPFN_ACCEPTEX lpfnAcceptEx = NULL;
GUID GuidAcceptEx = WSAID_ACCEPTEX;
DWORD dwBytes = 0;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
HANDLE hCompPort = INVALID_HANDLE_VALUE;
OVERLAPPED ol;
char buf[BUFSIZE];
// Init WinSock Lib ….
ListenSocket = WSASocket(AF_IPX, SOCK_STREAM, NSPROTO_SPX,
NULL, 0, WSA_FLAG_OVERLAPPED);
ClientSocket = WSASocket(AF_IPX, SOCK_STREAM, NSPROTO_SPX,
NULL, 0, WSA_FLAG_OVERLAPPED);
// Bind && Listen ….
// Associate the listening socket with the completion port
CreateIoCompletionPort((HANDLE)ListenSocket, hCompPort,
(u_long)0, 0);
// Get AccpetEx Function
WSAIoctl(ListenSocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&GuidAcceptEx,
sizeof(GuidAcceptEx),
&lpfnAcceptEx,
sizeof(m_WorkInfo.AcceptInfo.lpfnAcceptEx),
&dwBytes,
NULL,
NULL
);
ZeroMemory(buf,BUFSIZE);
ZeroMemory(&ol,sizeof(OVERLAPPED));
// Post Accept Message
lpfnAcceptEx(ListenSocket,
ClientSocket,
buf,
0,
sizeof(SOCKADDR_IN) 16,
sizeof(SOCKADDR_IN) 16,
&dwBytes,
&ol
);
}
需要注意的是,通过WSAIoctl获取AcceptEx函数指针时,只需要传递给WSAIoctl一个有效的SOCKET即可,该Socket的类型不会影响获取的AcceptEx函数指针。
如果不希望AcceptEx建立连接后等待用户发送数据,那么必须将第四个参数设为0。第5、6参数必须是对应SOCKET的地址类型的大小再加上16个字节。
为了使服务器能较好的处理用户连接请求,可采取如下两种策略:
A.设定两个界限值,使系统未处理的Accept操作保持在一个固定水平。推荐上限为10;
B.通过WSAEventSelect函数监听ListenSocket上的FD_ACCEPT事件。
当关闭完成端口时,如果还有未处理的Accepte操作,应该先关闭ListenSocket,然后在IOCP中,处理这些Accept操作(进行资源释放等),切记不要强行终止那些没有处理的Accept操作,否则会造成内存泄漏。
为防止恶意用户(建立连接后,不发送数据),可设置ListenSocket的SO_CONNECT_TIME属性。
如果希望ClientSocket具有和ListenSocket相同的属性,需要对ClientSocket调用SO_UPDATE_ACCEPT_CONTEXT。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/187947.html原文链接:https://javaforall.cn