我已经打电话WSARecv()回来了WSA_IO_PENDING.然后我RST从另一端发送了一个数据包.GetQueuedCompletionStatus()存在于另一个线程中的函数已FALSE按预期返回,但是当我调用时,WSAGetLastError()我得到了64而不是WSAECONNRESET.
那为什么WSAGetLastError()不回来WSAECONNRESET?
编辑:
我忘了提到当我WSAGetLastError()在失败后直接调用时WSARecv()(由于RST收到了数据包),返回的错误代码是WSAECONNRESET和不是64.
所以看起来返回的错误代码取决于在WSARecv()调用它之后是否直接失败,或者在检索完成数据包之后失败.
Han*_*ant 13
这是IOCP的一般问题,您正在对TCP/IP驱动程序堆栈进行低级调用.正如所有驱动程序在Windows中所做的那样,使用NTSTATUS错误代码报告失败.这里的预期错误是STATUS_CONNECTION_RESET.
这些本机错误代码需要转换为winapi错误代码.这种翻译通常是上下文敏感的,它取决于winapi库发出的驱动命令.换句话说,如果是执行转换的Winsock库,则只能获得WSAECONNRESET错误.但这不是你的程序中发生的事情,GetQueuedCompletionStatus()处理错误.
这是一个通用的辅助函数,可以处理任何设备驱动程序的IOCP.没有上下文,OVERLAPPED结构不足以指示I/O请求是如何开始的.转到这篇KB文章,它记录了从NTSTATUS错误代码到winapi错误代码的默认映射.GetQueuedCompletionStatus()使用的映射.列表中的相关条目是:
STATUS_NETWORK_NAME_DELETED ERROR_NETNAME_DELETED
STATUS_LOCAL_DISCONNECT ERROR_NETNAME_DELETED
STATUS_REMOTE_DISCONNECT ERROR_NETNAME_DELETED
STATUS_ADDRESS_CLOSED ERROR_NETNAME_DELETED
STATUS_CONNECTION_DISCONNECTED ERROR_NETNAME_DELETED
STATUS_CONNECTION_RESET ERROR_NETNAME_DELETED
Run Code Online (Sandbox Code Playgroud)
这些都是,不是很棒的选择.可能会回到很早的Windows,当Lanman成为首选的网络层时.WSAGetLastError()将ERROR_NETNAME_DELETED映射回WSA特定错误是无能为力的,当GetQueuedCompletionStatus()为线程设置"最后一个错误"代码时,NTSTATUS代码丢失.所以它没有,它只是返回它所能做的.
您期望的是WSAGetQueuedCompletionStatus()函数,因此使用Winsock规则可以正确地发生此错误转换.没有一个.这些天我更喜欢使用如何正确编写Windows代码的最终权限,可以从Reference Source获得.NET Framework源代码.我链接到SocketAsyncEventArgs.CompletionCallback()方法的源代码.其中包含密钥:
// The Async IO completed with a failure.
// here we need to call WSAGetOverlappedResult() just so Marshal.GetLastWin32Error() will return the correct error.
bool success = UnsafeNclNativeMethods.OSSOCK.WSAGetOverlappedResult(
m_CurrentSocket.SafeHandle,
m_PtrNativeOverlapped,
out numBytes,
false,
out socketFlags);
socketError = (SocketError)Marshal.GetLastWin32Error();
Run Code Online (Sandbox Code Playgroud)
或者换句话说,您必须额外调用WSAGetOverlappedResult()以从GetLastError()获取正确的返回值.这不是很直观:)
| 归档时间: |
|
| 查看次数: |
1158 次 |
| 最近记录: |