18.TCP链接的创建与终止

链接的创建与终止

经过以下命令让主机svr4与bsdi发起并终止链接服务器

image_1ciuvborm19vt1c6m1bhb1i8vmt99.png-29.3kB

下面为tcpdump输出的TCP报文段部分socket

image_1ciuvdlpa1g981ruv11r2104813tem.png-147.2kB

每行格式为源>目的:标志tcp

上图中的标志的解释大数据

image_1ciuvj3se1b7m1qvrvet1gv16ds13.png-82.5kB

  • 第1行,1415531521:1415531521(0)表示分组的开始序号为1415531521,结束序号也为1415531521,数据字节数为0。这是链接同步请求,没有任何数据交换
  • 第2行,ack 1415531522表明确认序号,这个值只有在ACK标志位为1时才显示
  • win 4096表示发送端通告的窗口大小
  • < mss 1024 >表示发送端指明的最大报文长度,发端不接收超过该长度的报文段

创建链接协议

image_1civ1rl5k11e9150i1c4a1g081p001g.png-152.4kB

三次握手:线程

  1. 客户端发送一个SYN段做为链接请求,初始化序号为1415531521
  2. 服务端响应一个SYN段,初始化序号为1823083521。同时发送确认报文,确认序号为1415531521+1=1415531522。一个SYN占用一个序号
  3. 客户端响应确认报文,确认序号为1823083521+1=1823083522

终止链接协议

一个TCP链接是全双工,数据在两个方向传递,所以若是要关闭TCP链接,必须单独关闭两个方向的链接设计

四次握手:3d

image_1civ9i8ha1nq132p1odatjh2531t.png-67kB

  1. 客户端发送FIN,请求关闭链接
  2. 服务端收到FIN后,响应ACK
  3. 服务端发送FIN,请求关闭链接
  4. 客户端收到FIN后,响应ACK

之因此比链接多一次握手,是由于TCP支持半关闭,容许一边关闭链接后另外一边仍能发送数据,因此没法合并报文5和报文6,二者之间仍然可能存在单向数据传输的报文。因此一旦使用了半关闭,这四次握手就会分红两个阶段执行code

创建链接超时

image_1cj0943mo1t991m4v61ij8k1otd2a.png-165.2kB

其中第一、2次请求间隔5.8秒,第二、3次请求间隔24秒,其中tos 0x10表明telnet将IP数据报服务类型字段设为最小时延orm

image_1cj0e26n51svo1vkh14eq13dl12f62n.png-81.6kB

上面显示的总耗时76秒,是由于在大多数实现中,新建链接的时间最长为75秒server

BSD TCP采用500ms定时器,在初始化设置时,第一个500ms内会在任意时刻滴答一下,致使第一个间隔不是6秒而是5.8秒,但第二个间隔倒是准确的24秒

image_1cj0ecv2o1km66if8fe1tfe40734.png-123.5kB

最大报文段长度

MSS,表示TCP传往另外一端最大数据块的长度。当创建TCP链接时,双方都要通告各自的MSS。如当A告知B MSS为1460时,表示B能够发给A的最大数据块长度就是1460

一般以太网将MSS设为MTU大小减去IP首部和TCP首部长度,即1500-20-20=1460

TCP的半关闭

TCP提供了发送端在结束发送后,依然能够接收数据的能力,这就是半关闭

在应用程序调用shutdown,而且第二个参数为1时,会使用半关闭。普通的close不会有半关闭。因此不多应用程序会使用到半关闭

为何要有半关闭?

image_1cj0lsfdthsnhlacpc62p1mih9.png-162.3kB

场景:当发送远程命令到目的主机执行时,命令发送完后,client就能结束数据发送,但仍然接收目的主机发回的执行结果,这就是半关闭状态,当目的主机发完数据时,结束数据发送,完成链接关闭。没有半关闭,目的主机没法知道client数据何时发完,也就没法执行命令并响应结果

TCP状态变迁图

image_1cj0m8gfv1pd89b81geukgs9aum.png-518.5kB

其中SYN收到就是SYN_RCVD

image_1cj0nsuqiirt1k2v1ng31dob1ped1g.png-185.3kB

经过上面两个图能够观察到

  • client从CLOSED到ESTABLISHED所须要发送和接收的报文
  • server从LISTEN到ESTABLISHED所须要发送和接收的报文
  • ESTABLISHED状态才能进行数据传输
  • client从ESTABLISHED到CLOSED所须要发送和接收的报文
  • server从ESTABLISHED到CLOSED再到LISTEN所须要发送和接收的报文

并不存在CLOSED这个状态,它是一个假象的状态起点和终点,因此server从CLOSED过分到LISTEN不须要特殊处理

TIME_WAIT状态

又称2MSL等待状态,即2倍的报文段最大生存周期

当TCP主动关闭一方发送最后一个ACK时,会进入TIME_WAIT状态,等待2MSL时间才能完全关闭链接

为何须要等待2MSL呢?

  1. 防止最后一个ACK丢失。若是真丢失,被动关闭一方会重发FIN(2MSL=MSL(丢失的ACK)+MSL(重发的FIN)
  2. 在2MSL期间不能复用链接(源IP、目的IP、源端口、目的端口的四元祖),避免原始链接中迷途的数据跑到新链接中

大部分TCP实现较为严格,在TIME_WAIT期间,没法复用端口

  • 若是客户端主动关闭链接,进入TIME_WAIT,因为客户端是随机端口,没法复用原来端口能够很容易作到
  • 若是服务端主动关闭链接,进入TIME_WAIT,因为服务端是知名端口,没法复用原来端口会致使重启服务耗时至少为2MSL。不少实现提供SO_REUSEADDR来绕过这个限制,保证服务端能够复用TIME_WAIT期间的端口

FIN_WAIT_2状态

当主动关闭一方发送FIN,并收到ACK后,会进入FIN_WAIT_2状态,直到被动关闭一方发送FIN,主动方才会响应ACK并进入TIME_WAIT状态

因此,若是被动关闭一方不关闭链接,会致使主动关闭一方永远处于FIN_WAIT_2状态,而被动关闭一方永远处于CLOSE_WAIT状态

复位报文段

当报文段发往一个socket时出现错误,TCP就会发出一个复位报文段。一般有如下三种场景:

  1. 到不存在的端口发起链接请求。当发送到目的端,发现端口不存在,UDP会响应一个ICMP端口不可达差错,TCP会响应复位报文段
  2. 异常终止一个链接。经过FIN正常关闭,可是须要处理排队的数据;复位报文段异常关闭,能够当即丢弃排队的数据
  3. 检测半打开链接。当一边异常关闭链接而另外一边不知道,这种是半打开链接。如server异常断电重启,client不知server的情况,继续发送报文,server收到后立马响应一个复位报文段

TCP选项

image_1cj94hccc4vb1r2m5je1u281as8p.png-89.3kB

如图显示了三个选项:

  1. 最大报文段长度
  2. 窗口扩大因子
  3. 时间戳

实际为了保证选项总长度是4字节的倍数,须要在其中填充无操做NOP选项

image_1cj94lvah1gjrf8lck71c6g1pq526.png-15.9kB

TCP服务器的设计

  • 当服务端监听链接时,会处于LISTEN状态
  • 当客户端请求到来时,会启动一个线程/进程去接收客户端链接请求
  • 当客户端服务端链接创建时,处于ESTABLISHED状态

image_1cjfq6vjkc5otqo1at41vtqcsi19.png-50.8kB

服务器能够限定本地监听的IP地址和远端请求的IP地址

链接队列

当服务器忙于处理客户端请求时,多的请求在链接创建后会放入链接队列。链接队列有如下规则:

  1. 监听链接请求的一端会有固定长度的链接队列,该队列存储已创建链接(完成了三次握手)的请求,稍后应用程序会从该队列中移除请求并处理
  2. 积压值(backlog)是这个队列的最大长度
  3. 当该队列已满,TCP不会将理会后续的链接请求(SYN),而且不会回复RST。RST表明这个请求是硬错误,不能重试。而不理会会让客户端请求超时,发现是一个软错误,会进行重试
相关文章
相关标签/搜索