4.7 关闭连接

1. “任意”解除连接

  • 所有 HTTP 客户端、服务器或代理都可以在任意时刻关闭一条 TCP 传输连接。通常会在一条报文结束时关闭连接(除非服务器怀疑出现了客户端或网络故障,否则就不应该在请求的中间关闭连接)。出错的时候,也可能在首部行的中间,或其他奇怪的地方关闭连接。
  • 对管道化持久连接来说,这种情形是很常见的。HTTP 应用程序可以在经过任意一段时间之后,关闭持久连接。比如,在持久连接空闲一段时间之后,服务器可能会决定将其关闭。
  • 但是,服务器永远都无法确定在它关闭“空闲”连接的那一刻,在线路那一头的客户端有没有数据要发送。如果出现这种情况,客户端就会在写入半截请求报文时发现出现了连接错误。

2. Content-Length 及截尾操作

  • 每条 HTTP 响应都应该有精确的 Content-Length 首部,用以描述响应主体的尺寸。
  • 一些老的 HTTP 服务器会省略 Content-Length 首部,或者包含错误的长度指示,这样就要依赖服务器发出的连接关闭来说明数据的真实末尾。
  • 客户端或代理收到一条随连接关闭而结束的 HTTP 响应,且实际传输的实体长度与 Content-Length 并不匹配(或没有 Content-Length)时,接收端就应该质疑长度的正确性。
  • 如果接收端是个缓存代理,接收端就不应该缓存这条响应(以降低今后将潜在的错误报文混合起来的可能)。代理应该将有问题的报文原封不动地转发出去,而不应该试图去“校正”Content-Length,以维护语义的透明性。

3. 连接关闭容限、重试以及幂等性

  • HTTP 应用程序要做好正确处理非预期关闭的准备。
  • 如果在客户端执行事务的过程中,传输连接关闭了,那么,除非事务处理会带来一些副作用,否则客户端就应该重新打开连接,并重试一次。
  • 副作用是很重要的问题。如果在发送出一些请求数据之后,收到返回结果之前,连接关闭了,客户端就无法百分之百地确定服务器端实际激活了多少事务。有些事务,比如 GET 一个静态的 HTML 页面,可以反复执行多次,也不会有什么变化。而其他一些事务,比如向一个在线书店 POST 一张订单,就不能重复执行,不然会有下多张订单的危险。
  • 幂等性:如果一个事务,不管是执行一次还是很多次,得到的结果都相同,这个事务就是幂等的。实现者们可以认为 GET、HEAD、PUT、DELETE、TRACE 和 OPTIONS 方法都共享这一特性。(基于 GET 构建动态表单的管理者们要确保这些表单是幂等的。)
  • 客户端不应该以管道化方式传送非幂等请求(比如 POST)。否则,传输连接的过早终止就会造成一些不确定的后果。要发送一条非幂等请求,就需要等待来自前一条请求的响应状态。
  • 注意:尽管用户 Agent 代理可能会让操作员来选择是否对请求进行重试,但一定不能自动重试非幂等方法或序列。比如,大多数浏览器都会在重载一个缓存的 POST 响应时提供一个对话框,询问用户是否希望再次发起事务处理。

4. 正常关闭连接

  • TCP 连接是双向的。TCP 连接的每一端都有一个输入队列和一个输出队列,用于数据的读或写。放入一端输出队列中的数据最终会出现在另一端的输入队列中。
    这里写图片描述

1. 完全关闭与半关闭

  • 应用程序可以关闭 TCP 输入和输出信道中的任意一个,或者将两者都关闭了。
  • 完全关闭:套接字调用 close() 会将 TCP 连接的输入和输出信道都关闭了。
  • 半关闭:套接字调用 shutdown() 单独关闭输入或输出信道。
    这里写图片描述

2. TCP 关闭及重置错误

  • 简单的 HTTP 应用程序可以只使用完全关闭。但当应用程序开始与很多其他类型的 HTTP 客户端、服务器和代理进行对话且开始使用管道化持久连接时,使用半关闭来防止对等实体收到非预期的写入错误就变得很重要了。
  • 关闭连接的输出信道:总是很安全的。连接另一端的对等实体会在从其缓冲区中读出所有数据之后收到一条通知,说明流结束了,这样它就知道你将连接关闭了。
  • 关闭连接的输入信道:比较危险,除非你知道另一端不打算再发送其他数据了。如果另一端向你已关闭的输入信道发送数据,操作系统就会向另一端的机器回送一条TCP“连接被对端重置”的报文,如下图。大部分操作系统都会将这种情况作为很严重的错误来处理,删除对端还未读取的所有缓存数据。对管道化连接来说,这是非常糟糕的事情。
    这里写图片描述

3. 正常关闭

  • 实现正常关闭的应用程序首先应该关闭它们的输出信道,然后等待连接另一端的对等实体关闭它的输出信道。当两端都告诉对方它们不会再发送任何数据(比如关闭输出信道)之后,连接就会被完全关闭,而不会有重置的危险。
  • 但不幸的是,无法确保对等实体会实现半关闭,或对其进行检查。因此,想要正常关闭连接的应用程序应该先半关闭其输出信道,然后周期性地检查其输入信道的状态(查找数据,或流的末尾)。如果在一定的时间区间内对端没有关闭输入信道,应用程序可以强制关闭连接,以节省资源。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值