gpt4 book ai didi

c++ - 从 IOCP 线程调用 WSAGetLastError() 返回不正确的结果

转载 作者:可可西里 更新时间:2023-11-01 17:35:13 31 4
gpt4 key购买 nike

我调用了 WSARecv(),它返回了 WSA_IO_PENDING。然后我从另一端发送了一个 RST 数据包。存在于另一个线程中的 GetQueuedCompletionStatus() 函数按预期返回了 FALSE,但是当我调用 WSAGetLastError() 时,我得到了 64 而不是 WSAECONNRESET

那么为什么 WSAGetLastError() 没有返回 WSAECONNRESET


编辑:

我忘了提到当我在 WSARecv() 失败后直接调用 WSAGetLastError() 时(因为 RST 数据包被接收),返回的错误代码是 WSAECONNRESET 而不是 64

所以看起来返回的错误代码取决于 WSARecv() 是在调用它之后直接失败,还是稍后在检索完成数据包时失败。

最佳答案

这是 IOCP 的一般问题,您正在对 TCP/IP 驱动程序堆栈进行低级调用。与 Windows 中的所有驱动程序一样,它会报告带有 NTSTATUS 错误代码的故障。此处的预期错误是 STATUS_CONNECTION_RESET。

这些 native 错误代码需要转换为 winapi 错误代码。此翻译通常上下文相关,它取决于发出驱动程序命令的 winapi 库。换句话说,如果是 Winsock 库进行了翻译,您只能返回 WSAECONNRESET 错误。但这不是您的程序中发生的情况,是 GetQueuedCompletionStatus() 处理了错误。

这是一个通用的辅助函数,可以处理任何设备驱动程序的 IOCP。没有上下文,OVERLAPPED 结构不足以表明 I/O 请求是如何开始的。转this KB article ,它记录了从 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

咳咳,这些并不是很好的选择。可能可以追溯到非常早期的 Windows,当时 Lanman 是首选的网络层。 WSAGetLastError() 无法将 ERROR_NETNAME_DELETED 映射回 WSA 特定错误,当 GetQueuedCompletionStatus() 为线程设置“最后一个错误”代码时,NTSTATUS 代码丢失。所以它不会,它只是返回它可以返回的内容。


期望的是一个 WSAGetQueuedCompletionStatus() 函数,因此可以使用 Winsock 规则正确地进行错误转换。没有一个。这些天我更喜欢使用关于如何正确编写 Windows 代码的最终权威,.NET Framework 源代码可从 Reference Source 获得。 .我链接到 SocketAsyncEventArgs.CompletionCallback() 方法的源代码。其中包含 key :

// 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();

或者换句话说,您必须额外调用 WSAGetOverlappedResult() 才能从 GetLastError() 获得正确的返回值。这不是很直观:)

关于c++ - 从 IOCP 线程调用 WSAGetLastError() 返回不正确的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28925003/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com