image.png
客户端:192.168.143.11,服务端:112.80.248.76

三次握手

客户端发起第一次握手

Frame中可以看到此为第一帧Frame Number: 1
image.png

Internet Protocol Version 4可以查看IP报文
image.png

Transmission Control Protocol可以查看TCP报文
从下图中可以看到,TCP报文中包括了:

  1. Source Port:63425源端口
  2. Destination Port:80目标端口
  3. Sequence Number:0序列号
  4. Acknowledgment Number:0确认号
  5. Flags
    1. SYN:1请求连接
  6. Window:65535协商窗口
  7. Options选项
    1. MSS:1460Maximun segment size
    2. NOPNo-Opration
    3. Window scale
    4. SACK permitted

image.png

TCP报文头部至少20个字节:

  1. 源端口和目标端口分别2个字节,就是16位,2**16 - 1所以最多65535个端口
  2. 序列号4个子节
  3. 确认号4个字节
  4. 标志位,滑动窗口等一起4个字节
  5. 包校验和,紧急指针一起4个字节

    为什么序列号要随机?

    Sequence Number(raw):2348159985
    为什么序列号要随机生成,为了防止伪造IP可伪造Acknowledgment Number只发起第一次握手和第三次握手,从而建立连接

    服务端响应第二次握手

    服务端发起响应:

  6. Sequence Number:0序列号

  7. Acknowledgment Number:1确认号
  8. Flags标志位
    1. SYN:1
    2. Acknowledgment:1
  9. Window:8192滑动窗口
  10. Options可选项
    1. MSS:1452
    2. Window scale:5

image.png

客户端响应第三次握手

客户端收到服务端的响应之后,发起响应:

  1. Sequence Number: 1序列号
  2. Acknowledgment Number:1确认号
  3. Flags标志位
    1. Acknowledgment:1
  4. Window:4096

    Http 请求

    三次握手建立连接之后,发起Http请求

  5. Sequence Number:1

  6. Acknowledgment Number:1
  7. Flags标志位
    1. Acknowledgment:1
    2. Push:1
  8. Window:4096

Http请求在TCP报文之上

Http报文

image.png

服务端TCP响应Http

服务端收到客户端的GET请求之后,发起TCP响应

  1. Sequence Number:1因为服务端还没开始发送数据,所以序列号是1
  2. Acknowledgment Number:78客户端已经发起GET请求,其中请求头77个字节,所以确认号是78
  3. Flags标志位
    1. Acknowledgment:1
  4. Window:908

    传输数据

    服务端发送数据

    服务端TCP响应完客户端HTTP GET请求之后,开始响应数据

第一波数据:

  1. Sequence Number:1
  2. Acknowledgment Number:78
  3. TCP Segment Len:1440
  4. Flags
    1. Acknowledgment:1
    2. Push:1

第二波数据:

  1. Sequence Number:1441
  2. Acknowledgment Number:78
  3. TCP Segment Len:1341
  4. Flags
    1. Acknowledgment:1
    2. Push:1

客户端响应第一波数据:

  1. Sequence Number:78
  2. Acknowledgment Number:1441
  3. Flags
    1. Acknowledgment:1

客户端响应第二波数据:

  1. Sequence Number:78
  2. Acknowledgment Number:2782
  3. Flags

    1. Acknowledgment:1

      四次挥手

      客户端检测到已发送完数据,则开始请求断开连接
  4. 客户端发起断开连接请求

    1. FlagsACK:1,Fin:1
  5. 服务端收到请求之后响应
    1. FlagsACK:1
  6. 服务端处理完成,发起断开连接请求:
    1. FlagsFin:1,ACK:1
  7. 客户端收到之后确认:

    1. FlagsACK:1

      消耗序列号的几种情况

  8. 客户端发起连接请求会消耗1个客户端序列号

  9. 服务端响应建立连接也会消耗1个服务端序列号
  10. 客户端发起断开连接请求会消耗1个客户端序列号
  11. 服务端发起断开连接请求也会消耗1个服务端序列号

总结:SYNFIN占序列号

为什么SYNFIN需要占用序列号

可以这样理解:
因为SYNFIN也是需要被确认的,只要是需要被确认的就需要占序列号

不然如果序列号不增加的话,举一个场景:
客户端接收到数据之后,发起断开连接FIN请求,此时服务端响应ACK,这里需要响应两个ACK
可是两个ACKAcknowledgment Number都是都是一样的,就无法确认服务器的ACK是对于哪个进行ACK