我目前正在尝试一些用于套接字编程的新库(IOCP).我偶然发现了AcceptEx功能来启用异步连接.
正如文件所说:
与accept函数不同,AcceptEx函数使用重叠的I/O. 如果您的应用程序使用AcceptEx,它可以使用相对较少的线程为大量客户端提供服务.与所有重叠的Windows功能一样,Windows事件或完成端口可用作完成通知机制.
但是当客户端连接时我没有收到任何完成.但是,当客户端发送数据时,我会完成.
这是我的代码:
DWORD dwBytes;
GUID GuidAcceptEx = WSAID_ACCEPTEX;
int iResult = WSAIoctl(m_hSocket, SIO_GET_EXTENSION_FUNCTION_POINTER,
&GuidAcceptEx, sizeof (GuidAcceptEx),
&m_lpfnAcceptEx, sizeof (m_lpfnAcceptEx),
&dwBytes, NULL, NULL);
if (iResult == SOCKET_ERROR)
{
CloseSocket();
}
Run Code Online (Sandbox Code Playgroud)
然后:
WSAOVERLAPPED olOverlap;
memset(&olOverlap, 0, sizeof (olOverlap));
char lpOutputBuf[1024];
int outBufLen = 1024;
DWORD dwBytes;
BOOL bRet = m_lpfnAcceptEx( m_hSocket, hSocket, lpOutputBuf,
outBufLen - ((sizeof (sockaddr_in) + 16) * 2),
sizeof (sockaddr_in) + 16, sizeof (sockaddr_in) + 16,
&dwBytes, &olOverlap);
if ( bRet == FALSE …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个可以同时支持多个客户端连接的服务器,所以我正在尝试使用IOCP.让我简要介绍一下我的代码流程,然后我可以解释一下我的问题.首先,服务器正在打开一个端口,用于监听和等待对新传入连接的"接受"调用.作为参考,我使用了与此处提到的相同的代码.因此,它接受每个新的传入连接并返回一个新的套接字描述符(sd),然后它标记为非阻塞:
arg = 1;
ioctlsocket(sd, FIONBIO, &arg);
Run Code Online (Sandbox Code Playgroud)
然后启用TCP_NODELAY:
level = IPPROTO_TCP;
optName = TCP_NODELAY;
value = 1;
setsockopt(sd, level, optName, (const char*)&value, sizeof(value));
Run Code Online (Sandbox Code Playgroud)
此后与IOCP端口关联:
CreateIoCompletionPort((HANDLE)sd, iocp_port, (DWORD)completion_key, 4);
Run Code Online (Sandbox Code Playgroud)
completion_key是一个类对象,它只是一个容器,它包含数据缓冲区,重叠缓冲区,查询类型的recv/send等,并在最后发出一个读取调用:
WSARecv(sd, wsabuf, 1, &bytes, &flags, overlapped, NULL);
Run Code Online (Sandbox Code Playgroud)
wsabuf和overlapped是completion_key对象的一部分.
在90%的情况下,它工作正常,即当此套接字上有一些传入数据时,"GetQueuedCompletionStatus"被取消阻止,并且它具有有效数据.但有时WSARecv调用返回错误,GetLastError()返回6,这是"无效句柄"错误.我有点困惑为什么会发生这样的事情.
我正在创建一个iocp端口的方式:
iocp_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
Run Code Online (Sandbox Code Playgroud)
并且有一些线程正在等待"GetQueuedCompletionStatus".
Microsoft 的I/O 完成端口文档指出:
请注意,虽然 [completion] 数据包按 FIFO 顺序排队,但它们可能会以不同的顺序出队。
我的理解是线程通过调用GetQueuedCompletionStatus从完成端口获取完成数据包。如果系统不能保证按 FIFO 顺序检索数据包,为什么系统会按 FIFO 顺序将数据包排队到完成端口?
根据我对IOCP到目前为止的理解,当我创建一个完成端口并将套接字关联到它时,当一个套接字准备好被读取时,通知将被发送到完成端口.
但是如何send()处理,我的意思是如果我想发送数据,我应该打电话send()吗?完成端口怎么样,是否收到任何通知send()?
我需要知道使用IOCP时的错误代码WSASend()和WSARecv()(除外WSA_IO_PENDING)是否表示套接字已断开连接.大多数错误代码都很明显,但我不确定以下内容:
错误代码WSASend():
WSAEINPROGRESSWSAENOBUFSWSA_OPERATION_ABORTED错误代码WSARecv():
WSAEFAULTWSAEINPROGRESS 我目前正在互联网上搜索自定义线程池实现.我找到了一个使用IOCP的实现.我想知道使用它们有什么好处?他们提供工作偷窃,或类似的东西,我真的能找到答案......
我最近在Windows平台上碰到了一个名为IOCP的东西,更精确:输入/输出控制端口.当需要同时容纳数千个用户时,这似乎是对服务器软件进行编码的最有效方式.(如果我错了,请纠正我,但每个套接字,轮询和异步回调(每个回调上的线程)都不够高效.)
我想知道是否有任何第三方库可以实现这个概念.我知道win32 api为我们提供了CreateIoCompletionPort,FreeBSD有kqueue和linux一般可以使用/ dev/epoll,它的工作方式有点类似......但是不存在处理这些东西的跨平台库(如boost :: thread)为了我?
我使用Socket类的异步/ IOCP方法,BeginSend()/ BeginRead()/ etc编写了一个TCP服务器.我想使用SslStream添加SSL功能,但是从界面看起来Socket和SslStream并不打算一起工作,特别是因为我根本不使用Streams而且SslStream似乎依赖于使用Stream来处理.
这是可能的,还是我在错误的地方?我是否需要设计自己的Stream子类,该子类将提供给我的Socket实例并指向SslStream?由于扩展问题,我的服务器使用IOCP对我很重要.
我需要在服务器中使用ip-address和客户端端口.使用IOCP在C++上编写的服务器,所以我不接受客户端,我创建新的套接字然后在这个就绪套接字上接受(AcceptEx)客户端.因为它结构sockaddr_in是不正确的.
我怎样才能做到这一点?
谢谢!
在《WinSock Programming Fundamental: A Compilation》一书中,IOCP有这个图:

我知道完成通知到达完成端口,并且四个排队的线程调用GetQueuedCompletionStatus()以获取完成数据包。但是在完成端口下面显示的另外两个工作线程是做什么的,是不是这些线程也调用了GetQueuedCompletionStatus()但是他们已经收到了一个完成包,现在正在处理呢?
Netty的I/O复用在Linux系统上依赖于epoll,但是在Windows操作系统上运行netty时性能一样吗?
Windows没有epoll,netty如何工作?iocp?
谢谢您的回答。
在新的0.5.1分支中,有一个Node.js的官方Windows可执行文件.Node.js的Linux版本使用已建立的库,例如v8,libev,libeio.
由于libev和libeio适用于*NIX平台; Node.js的Windows端口是否可供生产使用,还是仅用于开发?
我正在学习IOCP,并根据这篇文章:
要开始使用完成端口,我们需要创建一个完成端口,该端口依次创建许多并发线程(与完成端口一起存在的线程 - 不要与工作线程混淆).
我认为存在的唯一线程是我创建的用于从完成端口出列完成数据包的线程.完成端口创建的"并发线程"是什么?