关闭套接字而不等待发送成功-Winsock2非阻塞TCP套接字

Close socket without waiting for send to succeeed - Winsock2 non-blocking TCP socket

本文关键字:套接字 -Winsock2 TCP 成功 等待      更新时间:2023-10-16

我通过封装Winsock2 API的套接字库使用非阻塞套接字。WSAAsyncSelect()函数用于将套接字通知发送到窗口。(应用程序是单线程的)。

我正在努力实现以下开放式客户端套接字的目标:

  • 向服务器发送最后一条消息
  • 关上插座并毁坏窗户

我不想阻塞等待服务器ACK我的最后一条消息,因为这会给我的代码用户带来另一个延迟/失败点。这对我的协议来说不是一个重要的信息,只是一个很好的信息。

目前,我的代码最终调用Winsock2send()来发送最终消息,然后调用closesocket()。然而,我的TCP流(如Wireshark所示)看起来像:

// Calling send():
Me -> Host:  [PSH, ACK] 
// Calling closesocket():
Me -> Host:  [FIN, ACK] 
// Just after that:
Host -> Me:  [ACK]    
Host -> Me:  [ACK]
Host -> Me:  [ACK] Len=1380   // A response to my sent packet, that I don't care about
Me -> Host:  [RST, ACK]
Host -> Me:  [RST]
Host -> Me:  [PSH, ACK]  // Retransmission of that response
Me -> Host:  [RST]

因此,Windows发送了两个RST请求。我相信这是因为套接字在发送FIN之后接收到消息,所以它决定RST是必要的,但随后主机将其解释为重传请求。

如果我在调用closesocket之前将代码更改为等待一段时间,那么跟踪看起来非常不同:我的一端只发送[FIN, ACK],另一端发送回[FIN, ACK],并且没有RST。

我的问题是:如何在不阻塞的情况下整齐地关闭我的插座(即避免RST交换)?

我不想阻塞等待服务器确认我的最后一条消息,因为这会给我的代码用户带来另一个延迟/失败点。这对我的协议来说不是一个重要的信息,只是一个很好的信息。

我想你说的是应用程序级别的ACK。如果在未读数据到达之前关闭,则会触发对发件人的RST。你必须对此做出决定。要么它在协议中,要么它不在。