AcceptEx与WSAEventSelect和Accept

AcceptEx、WSAEventSelect和Accept是Windows Socket编程中常用的三种API函数,用于TCP服务器端接受客户端连接请求,但它们的使用方式和功能有一些不同。

一、Accept函数

Accept是Windows Socket编程中最基本的函数之一,用于在TCP服务器端接受客户端连接请求,函数原型如下:

```c++

SOCKET Accept(_In_ SOCKET s, _Out_opt_ struct sockaddr *addr, _Inout_opt_ int *addrlen);

```

参数说明:

① s:指定正在监听的套接字;

② addr:指向sockaddr结构体的指针,表示客户端的地址信息,可以为NULL;

③ addrlen:表示addr结构体的长度,可以为NULL。

函数返回值是一个新的套接字,用于和客户端之间的通信。

Accept函数的使用方式:

```c++

SOCKET listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

bind(listenSock, (SOCKADDR*)&serverAddr, sizeof(SOCKADDR));

listen(listenSock, 5);

SOCKADDR_IN clientAddr = { 0 };

int clientAddrLen = sizeof(clientAddr);

SOCKET clientSock = accept(listenSock, (SOCKADDR*)&clientAddr, &clientAddrLen);

```

Accept函数的缺点:

① Accept函数是阻塞型函数,即如果当前没有客户端请求连接,Accept函数会一直等待,直到接收到连接请求或者出现错误,这会导致服务器效率低下。

② 每次调用Accept函数时都需要重新获取客户端的IP地址和端口号,这会增加一定的开销。

③ Accept函数只能处理一个客户端连接请求,不能同时处理多个请求。

二、WSAEventSelect函数

WSAEventSelect是函数是I/O事件模型实现中经常使用的函数之一,它可以控制一个套接字的事件通知模式,使得我们不需要使用阻塞的方式等待事件的发生,可以将I/O事件通知机制的逻辑处理给操作系统来完成,从而提高服务器的效率,减轻了服务器的压力。

函数原型如下:

```c++

int WSAEventSelect(

_In_ SOCKET s,

_In_ WSAEVENT hEventObject,

_In_ long lNetworkEvents

);

```

参数说明:

① s:指定需要控制事件的套接字;

② hEventObject:事件对象句柄,表示事件通知机制的句柄,可以使用WSACreateEvent函数创建;

③ lNetworkEvents:表示需要控制的事件类型,具体的事件类型可以参考MSDN文档。

注意事项:

① 必须在创建套接字之后,但在绑定和监听之前使用WSAEventSelect来指定相应的事件;

② WSAEventSelect()将不会返回直到创建成功;

③ WSAEventSelect()只能在套接字上注册一种类型的网络事件,要使用不同类型的事件,必须调用WSAEventSelect()多次。

函数使用案例:

```c++

SOCKET listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

bind(listenSock, (SOCKADDR*)&serverAddr, sizeof(SOCKADDR));

listen(listenSock, 5);

HANDLE hAcceptEvent = WSACreateEvent();

WSAEventSelect(listenSock, hAcceptEvent, FD_ACCEPT);

while (true) {

int nIndex = WSAWaitForMultipleEvents(1, &hAcceptEvent, FALSE, WSA_INFINITE, FALSE);

if (nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT) {

break;

}

WSANETWORKEVENTS wne = { 0 };

WSAEnumNetworkEvents(listenSock, hAcceptEvent, &wne);

if (wne.lNetworkEvents & FD_ACCEPT) {

SOCKADDR_IN clientAddr = { 0 };

int clientAddrLen = sizeof(clientAddr);

SOCKET clientSock = accept(listenSock, (SOCKADDR*)&clientAddr, &clientAddrLen);

printf("接受客户端连接:%s : %d\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

}

}

```

三、AcceptEx函数

AcceptEx函数是Windows Socket编程中专门用于提高TCP服务器性能的函数之一,通过它可以实现异步接收TCP连接请求,提高服务器性能和效率。但是,需要注意的是,AcceptEx函数只能在Windows NT以及之后的版本中使用,而且使用该函数需要包含MSWSock.h头文件,并且连接时需要使用IoCompletionPort或者WSAEventSelect。

函数原型如下:

```c++

BOOL AcceptEx(

_In_ SOCKET sListenSocket,

_In_ SOCKET sAcceptSocket,

_In_ PVOID lpOutputBuffer,

_In_ DWORD dwReceiveDataLength,

_In_ DWORD dwLocalAddressLength,

_In_ DWORD dwRemoteAddressLength,

_Out_ LPDWORD lpdwBytesReceived,

_Inout_ LPOVERLAPPED lpOverlapped

);

```

参数说明:

① sListenSocket:指定监听套接字;

② sAcceptSocket:指定接受套接字;

③ lpOutputBuffer:指定输出缓冲区;

④ dwReceiveDataLength:指定要从客户端接收的数据长度;

⑤ dwLocalAddressLength:指定本地地址缓冲区长度;

⑥ dwRemoteAddressLength:指定远程地址缓冲区长度;

⑦ lpdwBytesReceived:指定接收到的字节数;

⑧ lpOverlapped:指定指向OVERLAPPED结构体的指针。

函数使用案例:

```c++

SOCKET hSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

bind(hSock, (SOCKADDR*)&serverAddr, sizeof(SOCKADDR));

listen(hSock, SOMAXCONN);

SOCKET hAcceptSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

char buff[sizeof(SOCKADDR_IN)*2 + 16] = { 0 };

WSABUF wsaBuf = { 0 };

wsaBuf.buf = buff;

wsaBuf.len = sizeof(buff);

DWORD dwBytes = 0;

OVERLAPPED ovl = { 0 };

ovl.hEvent = WSACreateEvent();

AcceptEx(

hSock, hAcceptSock, buff,

0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16,

&dwBytes, &ovl);

WSAWaitForMultipleEvents(1, &ovl.hEvent, TRUE, INFINITE, FALSE);

```

综合比较:

通过对以上三个函数的介绍和使用案例的展示,我们可以看出它们之间的异同。

① Accept函数的使用最为简单,可以用于实现TCP监听和客户端连接操作,但是效率较低,每次接受连接请求都需要重新获取客户端的地址信息,且无法同时接受多个连接请求。

② WSAEventSelect函数可以用于实现异步接收连接请求,提高服务器性能和效率,但需要结合Windows信号事件机制来实现,代码的复杂度相较Accept而言有所增加。

③ AcceptEx函数在实现了异步接收连接请求的同时,还可以指定缓冲区、缓冲区长度等参数,同时支持多个连接请求,具有性能优势。但它只能在Windows NT及之后的版本中使用,需要一定的编程经验和技巧。

因此,在使用这些函数时,需要综合考虑自身需求,选择最合适的API函数。

壹涵网络我们是一家专注于网站建设、企业营销、网站关键词排名、AI内容生成、新媒体营销和短视频营销等业务的公司。我们拥有一支优秀的团队,专门致力于为客户提供优质的服务。

我们致力于为客户提供一站式的互联网营销服务,帮助客户在激烈的市场竞争中获得更大的优势和发展机会!

点赞(108) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿
发表
评论
返回
顶部