3.5、关闭连接

所有 HTTP 客户端、服务器或代理都可以在任意时刻关闭一条 TCP 传输连接。

每条 HTTP 响应都应该有精确的 Content-Length 首部,用以描述响应主体的尺 寸。若实际传输的实体长度与 Content-Length 并不匹配(或没有 Content-Length)时,接收端就应该质疑长度的正确性。

如果一个事务,不管是执行一次还是很多次,得到的结果都相同,这个事务就是幂 等的。客户端不应该以管道化方式传送非幂等请求(比如 POST)。 否则,传输连接的过早终止就会造成一些不确定的后果。要发送一条非幂等请求, 就需要等待来自前一条请求的响应状态。

3.5.1、正常关闭连接

TCP连接是双向的,TCP 连接的每一端都有一个输入队列和一个 输出队列,用于数据的读或写。

输入输出信道

完全关闭与半关闭

完全关闭:TCP 连接的输入和输出信道都关闭,套接字调用 close()。

半关闭:TCP 连接的输入或输出信道关闭,套接字调用 shutdown()。

关闭连接的输出信道总是很安全的。

问题:

关闭连接的输入信道比较危险,除非你知道另一端不打算再发送其他数据了。比如你已经在一条持久连接上发送了10条管道式请求了,响应也已经收到了,正在操作系统的缓冲区中存着(但应用程序还未将其读走)。现在,假设你发送了第11条请求,但服务器认为你使用这条连接的时间已经够长了,决定将其关闭。那么你的第11条请求就会被发送到一条已关闭的连接上去,并会向你回送一条重置信 息。这个重置信息会清空你的输入缓冲区。当最终要去读取数据的时候,会得到一个连接被对端重置的错误,已缓存的未读 响应数据都丢失了。

解决: 想要正常关闭连接的应用程序应该先半关闭其输出信道,然后周期性地检查其输入信道的状 态(查找数据,或流的末尾)。如果在一定的时间区间内对端没有关闭输入信道,应 用程序可以强制关闭连接,以节省资源。