IOCP使用时常见的几个错误 (转)

在使用IOCP时,最重要的几个API就是GetQueueCompeltionStatus、WSARecv、WSASend,数据的I/O及其完成状态通过这几个接口获取并进行后续处理。

GetQueueCompeltionStatus attempts to dequeue an I/O completion packet from the specified I/O completion port. If there is no completion packet queued, the function waits for a pending I/O operation associated with the completion port to complete.

						BOOL WINAPI GetQueuedCompletionStatus(
  __in   HANDLE CompletionPort,
  __out  LPDWORD lpNumberOfBytes,
  __out  PULONG_PTR lpCompletionKey,
  __out  LPOVERLAPPED *lpOverlapped,
  __in   DWORD dwMilliseconds
);
				

If the function dequeues a completion packet for a successful I/O operation from the completion port, the return value is nonzero. The function stores information in the variables pointed to by the lpNumberOfBytes, lpCompletionKey, and lpOverlapped parameters.

除了关心这个API的in & out(这是MSDN开头的几行就可以告诉我们的)之外,我们更加关心不同的return & out意味着什么,因为由于各种已知或未知的原因,我们的程序并不总是有正确的return & out。

If *lpOverlapped is NULL and the function does not dequeue a completion packet from the completion port, the return value is zero. The function does not store information in the variables pointed to by the lpNumberOfBytes and lpCompletionKey parameters. To get extended error information, call GetLastError. If the function did not dequeue a completion packet because the wait timed out, GetLastError returns WAIT_TIMEOUT.

假设我们指定dwMilliseconds为INFINITE。

这里常见的几个错误有:

WSA_OPERATION_ABORTED (995): Overlapped operation aborted.

由于线程退出或应用程序请求,已放弃I/O 操作。

MSDN: An overlapped operation was canceled due to the closure of the socket, or the execution of the SIO_FLUSH command in WSAIoctl. Note that this error is returned by the operating system, so the error number may change in future releases of Windows.

成因分析:这个错误一般是由于peer socket被closesocket或者WSACleanup关闭后,针对这些socket的pending overlapped I/O operation被中止。

解决方案:针对socket,一般应该先调用shutdown禁止I/O操作后再调用closesocket关闭。

严重程度轻微易处理

WSAENOTSOCK (10038): Socket operation on nonsocket.

MSDN: An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.

成因分析:在一个非套接字上尝试了一个操作。

使用closesocket关闭socket之后,针对该invalid socket的任何操作都会获得该错误。

解决方案:如果是多线程存在对同一socket的操作,要保证对socket的I/O操作逻辑上的顺序,做好socket的graceful disconnect。

严重程度轻微易处理

WSAECONNRESET (10054): Connection reset by peer.

远程主机强迫关闭了一个现有的连接。

MSDN: An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.

成因分析:在使用WSAAccpet、WSARecv、WSASend等接口时,如果peer application突然中止(原因如上所述),往其对应的socket上投递的operations将会失败。

解决方案:如果是对方主机或程序意外中止,那就只有各安天命了。但如果这程序是你写的,而你只是hard close,那就由不得别人了。至少,你要知道这样的错误已经出现了,就不要再费劲的继续投递或等待了。

严重程度轻微易处理

WSAECONNREFUSED (10061): Connection refused.

由于目标机器积极拒绝,无法连接。

MSDN: No connection could be made because the target computer actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host—that is, one with no server application running.

成因分析:在使用connect或WSAConnect时,服务器没有运行或者服务器的监听队列已满;在使用WSAAccept时,客户端的连接请求被condition function拒绝。

解决方案:Call connect or WSAConnect again for the same socket. 等待服务器开启、监听空闲或查看被拒绝的原因。是不是长的丑或者钱没给够,要不就是服务器拒绝接受天价薪酬自主创业去了?

严重程度轻微易处理

WSAENOBUFS (10055): No buffer space available.

由于系统缓冲区空间不足或列队已满,不能执行套接字上的操作。

MSDN: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.

成因分析:这个错误是我查看错误日志后,最在意的一个错误。因为服务器对于消息收发有明确限制,如果缓冲区不足应该早就处理了,不可能待到send/recv失败啊。而且这个错误在之前的版本中几乎没有出现过。这也是这篇文章的主要内容。像connect和accept因为缓冲区空间不足都可以理解,而且危险不高,但如果send/recv造成拥堵并恶性循环下去,麻烦就大了,至少说明之前的验证逻辑有疏漏。

WSASend失败的原因是:The Windows Sockets provider reports a buffer deadlock. 这里提到的是buffer deadlock,显然是由于多线程I/O投递不当引起的。

解决方案:在消息收发前,对最大挂起的消息总的数量和容量进行检验和控制。

严重程度严重

本文主要参考MSDN

************* 说明 *************

Fox只是对自己关心的几个错误和API参照MSDN进行分析,不提供额外帮助。

转载于:https://www.cnblogs.com/duzouzhe/archive/2009/10/30/1592673.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现一个IOCP(Input/Output Completion Port)服务器,需要按照以下步骤进行: 1. 创建一个监听套接字(listening socket)并绑定到本地IP地址和端口号上。 2. 创建一个完成端口(completion port)并将监听套接字与之关联。 3. 开始监听连接请求,当有客户端连接请求到达,接收连接,创建一个新的套接字(client socket),并将其与完成端口关联。 4. 将新创建的套接字(client socket)加入到IOCP中,以便异步地接收客户端的数据请求。 5. 当客户端请求到达使用异步I/O操作,从套接字中读取数据,并将读取请求与完成端口关联。 6. 当读取完成,将读取请求与处理请求的工作线程关联,并将读取到的数据传递给处理线程进行处理。 7. 处理线程完成数据的处理后,将处理结果写回客户端,使用异步I/O操作将写入请求与完成端口关联。 8. 当写入完成,将写入请求与处理请求的工作线程关联,完成整个请求处理过程。 在实现IOCP服务器,需要注意以下几点: 1. 应避免使用阻塞I/O操作,使用异步I/O操作以提高服务器的并发性能。 2. 应充分利用完成端口和线程池等技术,提高服务器的吞吐量和可扩展性。 3. 应实现适当的协议处理逻辑,以保证服务器能够正确地处理客户端请求。 4. 应对客户端请求进行适当的安全性检查,以确保服务器的安全运行。 5. 应实现适当的错误处理逻辑,以便及发现和处理服务器中的错误和异常情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值