【发布时间】:2013-01-08 02:32:12
【问题描述】:
我正在使用完成端口在 Windows NT 中编写一个 tcp 服务器来利用异步 I/O。 我有一个 TcpSocket 类、一个 TcpServer 类和一些(虚拟函数)回调来在 I/O 操作完成时调用,例如onRead() 用于读取完成的时间。我还有 onOpen() 用于何时建立连接, onEof() 用于何时关闭连接,依此类推。 我总是有一个等待读取的套接字,所以如果套接字有效地获取数据(读取将在大小 > 0 时完成),它会调用 onRead(),而不是客户端从客户端关闭套接字 em>(读取将以size == 0完成)它调用onEof(),并且服务器知道客户端何时使用closesocket(server_socket)关闭套接字;从它的侧面。
一切正常,但我注意到一件事:
当我调用 closesocket(client_socket);在连接的服务器端端点上,而不是客户端,(设置 linger {true, 0} 与否),挂起的读取将作为错误完成, 也就是说,读取大小不仅是 == 0,而且 GetLastError() 也会返回错误:64,或 'ERROR_NETNAME_DELETED'。我在网上搜索了很多关于此的内容,但没有发现任何有趣的内容。
然后我问自己:但这是一个真正的错误吗?我的意思是,这真的可以被认为是错误吗?
问题是在服务器端,当我 closesocket(client_socket); 时会调用 onError() 回调;而不是 onEof()。所以我是这么想的:
如果我在收到此“ERROR_NETNAME_DELETED”“错误”时调用 onEof() 而不是 onError() 会怎样? 这会引入一些错误或未定义的行为吗? 让我问这个问题的另一个重要点是:
当我收到带有“ERROR_NETNAME_DELETED”的读取完成时,我检查了 OVERLAPPED 结构,特别是包含 NTSTATUS 错误代码的重叠->内部参数 的底层驱动程序。如果我们看到 NTSTATUS 错误代码列表 [http://www.tenox.tc/links/ntstatus.html] 我们可以清楚地看到'ERROR_NETNAME_DELETED'是由NTSTATUS 0xC000013B产生的,这是一个错误,但它被称为'STATUS_LOCAL_DISCONNECT'。好吧,它看起来不像是错误的名称。它看起来更像是 `ERROR_IO_PENDING',这是一个错误,但也是正确行为的状态。
那么如何检查 OVERLAPPED 结构的内部参数,当这是 == 到 'STATUS_LOCAL_DISCONNECT' 时,执行对 onEof() 回调的调用?会搞砸吗?
另外,我必须从服务器端说,如果我在调用之前调用 DisconnectEx() 关闭套接字(client_socket);我不会收到那个错误。但是我不想调用 DisconnectEx() 怎么办?例如。当服务器关闭并且不想等待所有 DisconnectEx() 完成,而只想关闭所有客户端的连接时。
【问题讨论】:
-
@Hans,我认为他很好地描述了他是如何遇到这个错误的。
标签: c++ winapi tcp network-programming iocp