TCP协议

  • 序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;序列号seq就是这个报文段中的第一个字节的数据编号。
  • 确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;序列号表示报文段携带数据的第一个字节的编号,而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。
  • 确认标志位ACK:占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效。
  • TCP包头中的序号是为了解决乱序的问题,给包编号可以确定先来后到。

  • TCP包头中的确认序号是为了解决不丢包的问题,发出去的包应该需要确认对方是否收到,如果没有收到就应该重新发送,直到送达。

  • 从IP层面来讲,如果网络状况比较差,则IP层的数据是没有任何可靠性保证的,而作为IP层的上一层TCP也无能为力,TCP层唯一能做的就是不断重传,在它的层面上通过各种算法努力保证可靠性。

  • TCP包头中的状态位比如:发起一个连接SYN,回复ACK,重新连接RST,结束连接FIN等。TCP是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更。

  • TCP包头中的窗口大小是为了做流量控制,通信双方各声明一个窗口,标识自己当前能够处理的能力。TCP还会做拥塞控制,控制发送的速度。
  • TCP的连接建立,常称为三次握手,因为三次就可以做到双方的消息都有去有回。具体过程如下:

      A.第一次握手是由客户端向服务端发起的,是用来去发起一个连接建立的请求,在报文中,SYN位会被标记为1,产生一个随机序列号x;

      B.第二次握手是由服务器向客户端发起的,是服务器来确认一个请求连接的,在报文中,ACK位和SYN位都会被标记为1,产生一个随机序列号y,确认序号ack = x + 1;

      C.第三次握手是客户端发给服务器的,是对服务器的上一个报文的一个确认报文,这个报文中的ACK被标记为1,序列号为x+1,确认序号ack = y + 1。

    概括为:客户端 -> SYN -> 服务端

             服务端 -> SYN/ACK -> 客户端

             客户端 -> ACK -> 服务端

  • 三次握手除了双方建立连接外,主要还是为了沟通TCP包的序号的问题。每个连接都要有不同的序号,这个序号的起始序号是随着时间变化的。

  • 双方建立连接后,为了维护这个连接,双方都要维护一个状态机,在连接建立的过程中,双方的状态变化时序图如图所示。具体为:

 

    A.一开始,左边的客户端和右边的服务端都处于CLOSED状态,先是服务端主动监听某个端口,处于LISTEN状态;
    B.然后客户端主动发起连接SYN,之后处于SYN-SENT状态;
    C.服务端收到发起的连接,返回SYN,并且回复客户端的SYN,之后处于SYN-RCVD状态;
    D.客户端收到服务端发送的SYN和ACK之后,发送ACK的ACK,之后处于ESTABLISHED状态;
    E.服务端收到ACK的ACK之后,也处于ESTABLISHED状态。

  • TCP的连接结束,常成为四次挥手。具体过程如下:

  A.第一次挥手是客户端向服务器发起的,这个时候客户端已经完成了数据发送,会发起一个包去进行连接断开的请求,这个报文中的FIN位被标记为1,产生一个随机序列号u;

  B.第二次挥手是服务器发给客户端的,这个报文是用来确认上一个客户端断开连接请求的一个报文,ACK被标记为1,产生一个随机序列化v,确认序号ack = u + 1;
  C.第三次挥手同样是服务器发给客户端的,此时服务器的数据如果也发送完毕的话,服务器会向客户端发起一个断开连接的申请,在这个报文中,ACK和FIN位都会被标记为1,产生一个随机序列号w,确认序号ack = u + 1;
  D.第四次挥手是客户端发给服务器的,是用来确认服务器的上一个断开连接的,ACK位被标记为1,序列号为u+1,确认序号ack = w + 1。
  概括为:客户端 -> FIN -> 服务端
      服务端 -> ACK -> 客户端
      服务端 -> ACK/FIN -> 客户端
      客户端 -> ACK -> 服务端

 

  • TCP四次挥手时的状态变化:
  1. 客户端先向服务器发送FIN报文,请求断开连接,其状态变为FIN_WAIT1;
  2. 服务器收到FIN后向客户端发送ACK,服务器的状态围边CLOSE_WAIT;
  3. 客户端收到ACK后就进入FIN_WAIT2状态,此时连接已经断开了一半了。如果服务器还有数据要发送给客户端,就会继续发送;
  4. 直到服务器发完数据,就会发送FIN报文,此时服务器进入LAST_ACK状态;
  5. 客户端收到服务器的FIN后,马上发送ACK给服务器,此时客户端进入TIME_WAIT状态;
  6. 再过了2MSL长的时间后进入CLOSED状态。服务器收到客户端的ACK就进入CLOSED状态。
  • MSL是报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为TCP报文是基于IP协议的,而IP头中有一个TTL域,是IP数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减1,当此值为0则数据报将被丢弃,同时发送报文通知源主机。协议规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。

  • 将连接建立和连接断开的两个时序状态图综合起来,就得到著名的TCP状态机。
  • TCP协议为了保证顺序性,每一个包都有一个ID序号。在建立连接时,会商定起始的ID序号,然后按照ID一个个发送;为了保证不丢包,对于发送的包都要进行应答,但是这个应答不是一个个来的,而是会应答某个之前的ID,表示都收到了,这种模式称为累计确认或者累计应答。

  • 为了记录所有发送的包和接收的包,TCP需要发送端和接收端分别都有缓存来保存这些记录。
  • 发送端缓存里的包是按照包的ID一个个排列,根据处理的情况分成四个部分:

    第一部分:发送了并且已经确认的。

    第二部分:发送了并且尚未确认的。

    第三部分:没有发送,但是已经等待发送的。

    第四部分:没有发送,并且暂时还不会发送的。

  • 发送端缓存区分第三和第四部分是为了做流量控制,在TCP里,接收端会给发送端报一个窗口的大小,这个窗口的大小应该等于第二部分加上第三部分,超过这个窗口的,接收端处理不过来,就不能发送。

  • 对于接收端,它的缓存里记录三部分内容:

    第一部分:接受并且确认过的。

    第二部分:还没接收,但是马上就能接收的。

    第三部分:还没接收,也没法接收的。

  • 顺序问题、丢包问题、流量控制都是通过滑动窗口来解决。拥塞控制通过拥塞窗口来解决。

 

posted @ 2020-07-11 21:19  孔子?孟子?小柱子!  阅读(157)  评论(0编辑  收藏  举报