Windows 套接字:如何在非阻塞 connect() 上立即检测 TCP RST?

Windows sockets: How to immediately detect TCP RST on nonblocking connect()?

提问人:bonsaiviking 提问时间:9/1/2020 最后编辑:bonsaiviking 更新时间:9/9/2020 访问量:864

问:

我们的软件(Nmap 端口扫描器)需要快速确定非阻塞 TCP 套接字的状态。我们使用 select() 来监视大量套接字,而 Windows 擅长在成功时通知我们。但是,如果端口已关闭并且目标发送 TCP RST,则 Windows 将继续尝试几次,然后再通知 ,并且套接字错误符合预期。但是,我们的应用程序有自己的超时时间,并且通常会在 Windows 放弃之前将连接标记为超时。我们希望尽可能接近 Linux 的行为,即在收到第一个 RST 后立即通知。connect()exceptfdsWSAECONNREFUSEDECONNREFUSED

我们尝试使用TCP_MAXRT套接字选项,这可以立即向我们发出信号,但结果(对于关闭的端口)始终是 ,这使得无法区分关闭 (RST) 和过滤/防火墙(网络超时),这使我们回到了原来的问题。确定这种区别是我们应用程序的核心功能。select()WSAETIMEDOUT

那么,在 Windows 上确定非阻塞套接字是否已收到连接重置的最佳方法是什么?connect()

编辑补充:这里的核心问题是 Microsoft 关于套接字选项的文档中的这一行:“此每个套接字错误代码并不总是立即设置。如果立即设置,我们可以在连接超时之前检查它。SO_ERROR

Windows 选择 TCP Winsock Winsock2

评论

1赞 user207421 9/9/2020
你在这里可能不走运。我认为根本问题就在于此。如果积压队列已满,BSD 派生的 TCP 会丢弃传入的 SYN,这在客户端与主机或网络关闭时无法区分,因此重试,这是合理的:如果获得 RST,则意味着没有侦听套接字,因此它会立即返回。另一方面,如果积压工作队列已满,Windows 会发出 RST,因此客户端无法将该条件与无侦听套接字区分开来,因此它会在两者上重试,这在无侦听套接字上是无 pont。我不知道你是否可以解决这个问题。connect()connect()
0赞 bonsaiviking 9/10/2020
@MarquisofLorne 不过,这是非常有用的信息,谢谢!

答: 暂无答案