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

时间:2014-09-08 03:29:20

标签: c++ windows tcp winsock2

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

我正在尝试为开放客户端套接字实现以下目标:

  • 向服务器发送最终消息
  • 关闭套接字并销毁窗口

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

目前,我的代码最终调用Winsock2 send()发送最终消息,然后调用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交换)?

1 个答案:

答案 0 :(得分:1)

  

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

我假设您正在谈论应用程序级别的ACK。如果您在发送者到达之前关闭,未读数据将激发RST给发件人。你必须决定这一点。要么它在协议中,要么它不是。