使用 WSARecv() 和 IOCP 时如何知道套接字何时收到了 FIN 数据包?

Posted

技术标签:

【中文标题】使用 WSARecv() 和 IOCP 时如何知道套接字何时收到了 FIN 数据包?【英文标题】:How to know when the socket has received a FIN packet when using WSARecv() and IOCP? 【发布时间】:2015-03-06 12:41:46 【问题描述】:

当使用阻塞套接字和recv()函数时,当套接字收到一个FIN包时,recv()会返回0

但是,在使用WSARecv()和IOCP时,如何知道socket何时收到了一个FIN包呢?我认为lpNumberOfBytesRecvd 也将设置为0,但我不确定。

【问题讨论】:

【参考方案1】:

如果FIN 到达时WSARecv() 调用正在进行,那么您将成功完成并将lpNumberOfBytesRecvd 设置为0。

如果在FIN 到达之后发起WSARecv() 调用,那么您可能会从WSARecv() 调用中收到WSAESHUTDOWN 错误。

当我获得第一个“客户端关闭”(即零字节读取返回)时,我倾向于在套接字上发出shutdown(s, SD_RECEIVE),因为这会给出上述可预测的行为并避免通过 IOCP 进行后续尝试接收...

【讨论】:

WSARecv()返回错误时的错误代码是什么(即WSAGetLastError()返回什么)? 在发出完成的情况下,如果对端正常断开连接(发送FIN),则报告 0 字节的 I/O 成功。但是如果连接异常丢失,则会报告 I/O 失败并带有错误代码,例如ERROR_NETNAME_DELETED (64)。确保您正在考虑套接字故障和异常断开连接。并非所有客户端都能正常断开连接,否则网络故障有时可能会丢失 FIN 是的,但这不是问题所在。 :) 完成失败的方式有很多...这实际上不是失败路径,而是读取 0 字节的成功路径。 我在FIN包到达后调用了WSARecv()WSARecv()返回了0WSAGetLastError()也返回了0 @RemyLebeau FIN 就像 TCP 数据段一样接受确认和重传。

以上是关于使用 WSARecv() 和 IOCP 时如何知道套接字何时收到了 FIN 数据包?的主要内容,如果未能解决你的问题,请参考以下文章

WSASend() 和 WSARecv() 的所有错误代码是不是意味着套接字已断开连接?

IOCP 接收和发送

当目前没有 wsarecv 时,传入数据会发生啥

io 完成端口问题,每个 GetQueuedCompletionStatus 调用多个 wsarecv 或 wsasend

如何知道完成数据包是针对 WSASend() 还是 WSARecv() 还是 AcceptEx()?

使用套接字时,哪些 IO 操作会导致完成数据包发送到完成端口?