TCP三次握手

TCP三次握手过程

TCP在传输数据之前,要先三次握手建立连接。

  • 一开始。客户端和服务端都处于 CLOSE 状态,首先是服务端监听某个端口出于 LISTEN 状态。
  • 然后客户端发起SYN请求,之后出于SYN-SEND状态。
  • 服务端收到发起的连接,返回 SYN,并且 ACK 客户端的 SYN,之后处于 SYN-RCVD 状态。
  • 客户端收到服务端发送的 SYN 和 ACK 之后,发送对 SYN 确认的 ACK,之后处于 ESTABLISHED 状态,因为它一发一收成功了。
  • 服务端收到 SYN 的 ACK 之后,处于 ESTABLISHED 状态,因为它也一发一收了。

三次握手的主要目的是为了保证双发都有发送和接收的能力。

TCP数据分割

如果应用层发送的数据比较大,超过了MSS(Maximum Segment Size,最大报文段),这时传输层需要把应用层传下来的数据拆分成一块一块的数据发送,而不是一次性发送所有的数据。

  • MTU:一个网络包的最大长度,以太网中一般是1500个字节。
  • MSS:除去TCP和IP的头部,一个网络包所能容纳的 TCP 数据的最大长度。默认情况下,一般是1460个字节。

TCP头部

  • 计算机上的进程要和其他进程通信是要通过计算机端口的,而一个计算机端口某个时刻只能被一个进程占用,所以通过指定源端口和目标端口,就可以知道是哪两个进程需要通信。源端口、目标端口是用16位表示的,可推算计算机的端口个数为2^16个。
  • 序号是为了解决包乱序的问题,因为一个应用程序的数据库可能会被分割成段进行发送,就收方在接收到数据时,可以根据序号重新组合数据。
  • 确认号是为了确认发出去的包接收方是否已经收到,如果没有收到就重发,直到收到。这个是为了解决不丢包的问题。
  • 首部长度代表TCP数据报头部的长度,即图中固定部分的长度加上选项部分,从图中可以看出,TCP首部最小的长度是20个字节,最大的长度是60个字节,因为首部长度是4位 2^4=16(0...15),15*4=60,选项部分的最大长度是40个字节。
  • URG表示本报文段中发送的数据是否包含紧急数据。URG=1,表示有紧急数据。后面的紧急指针字段只有当URG=1时才有效。
  • ACK表示是否前面的确认号字段是否有效。ACK=1,表示有效。只有当ACK=1时,前面的确认号字段才有效。TCP规定,连接建立后,ACK必须为1。
  • PSH告诉对方收到该报文段后是否应该立即把数据推送给上层。如果为1,则表示对方应当立即把数据提交给上层,而不是缓存起来。
  • RST只有当RST=1时才有用。如果你收到一个RST=1的报文,说明你与主机的连接出现了严重错误(如主机崩溃),必须释放连接,然后再重新建立连接。或者说明你上次发送给主机的数据有问题,主机拒绝响应。
  • SYN在建立连接时使用,用来同步序号。当SYN=1,ACK=0时,表示这是一个请求建立连接的报文段;当SYN=1,ACK=1时,表示对方同意建立连接。SYN=1,说明这是一个请求建立连接或同意建立连接的报文。只有在前两次握手中SYN才置为1。
  • FIN标记数据是否发送完毕。如果FIN=1,就相当于告诉对方:“我的数据已经发送完毕,你可以释放连接了”。
  • 窗口大小表示现在运行对方发送数据的数量。也就是告诉对方,从本报文段的确认序号开始允许对方发送的数据量。
  • 校验和提供额外的可靠性,保证数据库的完整性。
  • 紧急指针标记紧急数据在数据字段中的位置。
  • 选项部分
    • MSS最大报文段长度(Maxium Segment Size)指明数据字段的最大长度,数据字段的长度加上TCP首部的长度才等于整个TCP报文段的长度。MSS值指示自己期望对方发送TCP报文段时那个数据字段的长度。通信双方可以有不同的MSS值。如果未填写,默认采用536字节。MSS只出现在SYN报文中。即:MSS出现在SYN=1的报文段中。
    • 窗口扩大选项(Windows Scaling)由于TCP首部的窗口大小字段长度是16位,所以其表示的最大数是65535。但是随着时延和带宽比较大的通信产生(如卫星通信),需要更大的窗口来满足性能和吞吐率,所以产生了这个窗口扩大选项。
    • SACK选择确认项(Selective Acknowledgements):用来确保只重传缺少的报文段,而不是重传所有报文段。比如主机A发送报文段1、2、3,而主机B仅收到报文段1、3。那么此时就需要使用SACK选项来告诉发送方只发送丢失的数据。那么又如何指明丢失了哪些报文段呢?使用SACK需要两个功能字节。一个表示要使用SACK选项,另一个指明这个选项占用多少字节。描述丢失的报文段2,是通过描述它的左右边界报文段1、3来完成的。而这个1、3实际上是表示序列号,所以描述一个丢失的报文段需要64位即8个字节的空间。那么可以推算整个选项字段最多描述(40-2)/8=4个丢失的报文段。
    • 时间戳选项(Timestamps):可以用来计算RTT(往返时间),发送方发送TCP报文时,把当前的时间值放入时间戳字段,接收方收到后发送确认报文时,把这个时间戳字段的值复制到确认报文中,当发送方收到确认报文后即可计算出RTT。也可以用来防止回绕序号PAWS,也可以说可以用来区分相同序列号的不同报文。因为序列号用32为表示,每2^32个序列号就会产生回绕,那么使用时间戳字段就很容易区分相同序列号的不同报文。
    • NOP(NO-Operation):它要求选项部分中的每种选项长度必须是4字节的倍数,不足的则用NOP填充。同时也可以用来分割不同的选项字段。如窗口扩大选项和SACK之间用NOP隔开。

参考

https://blog.csdn.net/wilsonpeng3/article/details/12869233