c++ - TCP - 如果客户端在服务器 accept() 之前调用 close() 会怎样

标签 c++ c sockets networking tcp

在 C/C++ 中,如果客户端和服务器完成 3 次握手并且此连接位于服务器的积压(监听队列)中。在服务器调用 accept() 之前, 如果客户调用 close() 会发生什么.这个连接会从积压中删除吗?
现实世界的情况是,服务器有时太忙而无法立即接受每个连接。所以会有一些连接在积压中等待。客户端对来自服务器的第一个响应有超时。如果发生超时,它将调用 close()然后重试或其他。此时,我想知道服务器的积压是否会从积压中删除连接。
请分享你的想法。欣赏它!

最佳答案

一般来说,如果客户调用close() , 客户端协议(protocol)栈会发送一个 FIN 来表示客户端发送完毕,并等待服务器发送一个 FIN,ACK 给客户端(这在服务器接受连接之前不会发生,因为我们将见),然后客户端将确认。这将是 TCP 连接的正常终止。
然而,由于一个 TCP 连接由两个或多或少独立的流组成,所以从客户端发送 FIN 确实只是客户端完成发送数据的声明(这通常称为“半关闭”),实际上并不是在 TCP 协议(protocol)级别关闭连接的请求(尽管更高级别的协议(protocol)通常会以这种方式解释它,但它们只能在连接被接受并且它们已经读取返回 0 字节后才能这样做,以便了解客户写完了)。服务器仍然可以继续发送数据,但是由于客户端调用了close() ,不再可能将此数据传递给客户端应用程序。如果服务器进一步发送数据,客户端上的协议(protocol)栈将响应复位,导致 TCP 连接异常终止。如果客户端在声明发送数据完成后,确实希望继续从服务器接收数据,它应该通过调用 shutdown(sock,SHUT_WR) 来实现。而不是调用close() .
所以这意味着超时并且通常由客户端关闭的连接通常会在服务器上保持事件状态,并且服务器将能够接受它们,读取请求,处理请求并发送回复,并且只有然后发现当客户端返回重置时,应用程序无法再读取回复。我说“一般”的原因是防火墙、代理和操作系统协议(protocol)栈都限制了 TCP 连接可以保持半关闭状态的时间,这通常违反相关的 TCP RFC,但出于“有效”的原因,例如处理 DDOS。
我认为您担心的是,由于客户端超时和重试,过载的服务器会进一步过载,根据我之前的解释,我认为这是正确的。为了避免这种情况,客户端超时可以在调用 close() 之前将 SO_LINGER 设置为 0。这将导致发送复位以导致立即异常终止。我还建议在超时时使用指数回退来进一步减轻对过载服务器的影响。

关于c++ - TCP - 如果客户端在服务器 accept() 之前调用 close() 会怎样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63185837/

相关文章:

C++ 编写内联函数作为参数传递

c++ - 窗口关闭时 OpenCV 中止(核心转储)

c++ - Solaris 进程内存使用量增加但不会永远增加

c - BNF 到 Lex 到 C 语言的解析器

java - 如何通过 Android 访问 SSL 连接?

linux - 使用 netcat 通过服务器套接字连续发送文件的内容

c++ - iOS集成unity 4.6.3项目(64位&& IL2CPP)。出现如下这样的错误,如何解决呢?

c - C中的宽度格式化程序

c - 在同一线程中多次锁定互斥量

java - 一台服务器支持多个客户端 Java