一 TCP:传输控制协议报文格式

1 TCP服务

  • 提供面向连接、可靠的字节流服务

  • 面向连接意味着两方通信,不支持多播和广播

  • 可靠性的支持

    • 应用数据被分割成TCP认为最适合发送的数据块。由TCP传递给IP的信息单位称为报文段或段(segment)。
    • 当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
    • 当TCP收到发自TCP连接另一端的数据,它将响应一个确认
    • TCP将保持它首部和数据的检验和
    • TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。
    • IP数据报会发生重复,TCP的接收端必须丢弃重复的数据。
    • TCP还能提供流量控制,TCP连接的每一方都有固定大小的缓冲空间,防止较快主机致使较慢主机的缓冲区溢出。
    • TCP对字节流的内容不作任何解释。对字节流的解释由TCP连接双方的应用层解释。

2 TCP首部

  • TCP首部为20个字节
  • 端口号和目的端口号 :4个字节,用于寻找发端与收端的应用进程。
  • 32位序号:4个字节,用于识别从TCP发端向收端发送的数据字节流,循环利用,逐个递增。
  • 32位确认序号:4个字节,上次已成功收到数据字节序号加1(只有在ACK标志为1时,该字段才有效)
  • 首部长度:4位,用于标识首部的长度,即为5 * 4~15 * 4字节等于20~60字节(固定报头(20字节) + 可选选项)
  • 标志比特:
    • URG:紧急指针
    • ACK:确认序号有效
    • PSH:接受方应尽快将报文段交给应用层
    • RST:重建连接
    • SYN:同步序号用来发起一个连接
    • FIN:发端完成发送任务
  • 窗口大小:用于流量控制,最大为65535字节(16位)
  • 检验和:覆盖整个TCP报文段(TCP首部和数据),发端计算和存储,收端验证
  • 紧急指针:当URG为1时,才有效。

二 TCP连接的建立与终止

1 连接的建立与终止

(1)建立连接协议(三次握手连接)

  • Client发送SYN段指明打算连接Serer的端口以及初始序号(ISN),SYN为1
  • Server响应Server的初始序号(ISN)作为应答,同时将确认序号设置为Client的ISN+1以对Client的SYN报文进行确认。
  • Client将确认序号设置为Server的ISN+1以对Server的SYN报文进行确认。

(2)WireShark抓包分析三次握手连接

# client的SYN报文
Transmission Control Protocol, Src Port: 1682, Dst Port: 1883, Seq: 0, Len: 0
Source Port: 1682 # 源端口
Destination Port: 1883 # 目标端口
Sequence number: 0 (relative sequence number) # 序号
Acknowledgment number: 0 # 确认序号
1000 .... = Header Length: 32 bytes (8) # 首部长度
Flags: 0x002 (SYN) # 标识符
Window size value: 64240 # 窗口大小
Checksum: 0xa6f3 [unverified] # 检验和
Urgent pointer: 0 # 由于URG为0,所以紧急指针为0
Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted # 可选选项,后续讲解
TCP Option - Maximum segment size: 1460 bytes # 最大报文端长度
TCP Option - No-Operation (NOP) # 无操作
TCP Option - Window scale: 8 (multiply by 256) # 窗口扩大因子
TCP Option - No-Operation (NOP)
TCP Option - No-Operation (NOP)
TCP Option - SACK permitted # server的响应报文和SYN报文
Transmission Control Protocol, Src Port: 1883, Dst Port: 1682, Seq: 0, Ack: 1, Len: 0
Source Port: 1883
Destination Port: 1682
Sequence number: 0 (relative sequence number)
Acknowledgment number: 1 (relative ack number) # client的Squence number plus one
1000 .... = Header Length: 32 bytes (8)
Flags: 0x012 (SYN, ACK) # 设置SYN和ACK(响应)
Window size value: 14600
Checksum: 0xfd7c [unverified]
Urgent pointer: 0
Options: (12 bytes), Maximum segment size, No-Operation (NOP), No-Operation (NOP), SACK permitted, No-Operation (NOP), Window scale
TCP Option - Maximum segment size: 1412 bytes
TCP Option - No-Operation (NOP)
TCP Option - No-Operation (NOP)
TCP Option - SACK permitted
TCP Option - No-Operation (NOP)
TCP Option - Window scale: 6 (multiply by 64) # client的响应报文
Transmission Control Protocol, Src Port: 1682, Dst Port: 1883, Seq: 1, Ack: 1, Len: 0
Source Port: 1682
Destination Port: 1883
Sequence number: 1 (relative sequence number)
Acknowledgment number: 1 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x010 (ACK)
Window size value: 259
Checksum: 0xa6e7 [unverified]
Urgent pointer: 0

(3)连接终止协议

  • Client发送FIN报文,此时Client不再发送业务数据到Server,并等待Server的响应报文(Client应用程序关闭)
  • Server收到Client的报文,响应ACK报文。
  • Server发送FIN报文,此时双方都不再发送业务数据数据,并等待Client的响应报文(Server应用程序关闭))
  • Server收到Client的ACK报文即终止连接。

(4)WireShark抓包分析正常关闭

# Client发送FIN报文
Transmission Control Protocol, Src Port: 1682, Dst Port: 1883, Seq: 3, Ack: 1, Len: 0
Source Port: 1682
Destination Port: 1883
Sequence number: 3 (relative sequence number)
Acknowledgment number: 1 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x011 (FIN, ACK) # ACK是由于需要响应先前的交互
Window size value: 259
Checksum: 0xa6e7 [unverified]
Urgent pointer: 0 # Server发送ACK
Transmission Control Protocol, Src Port: 1883, Dst Port: 1682, Seq: 1, Ack: 4, Len: 0
Source Port: 1883
Destination Port: 1682
Sequence number: 1 (relative sequence number)
Acknowledgment number: 4 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x011 (FIN, ACK)
Window size value: 229
Checksum: 0x759f [unverified]
Urgent pointer: 0 # Server发送FIN
Transmission Control Protocol, Src Port: 1883, Dst Port: 1682, Seq: 1, Ack: 4, Len: 0
Source Port: 1883
Destination Port: 1682
Sequence number: 1 (relative sequence number)
Acknowledgment number: 4 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x011 (FIN, ACK)
Window size value: 229
Checksum: 0x759f [unverified]
Urgent pointer: 0 # Client发送ACK
Transmission Control Protocol, Src Port: 1682, Dst Port: 1883, Seq: 4, Ack: 2, Len: 0
Source Port: 1682
Destination Port: 1883
Sequence number: 4 (relative sequence number)
Acknowledgment number: 2 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x010 (ACK)
Window size value: 259
Checksum: 0xa6e7 [unverified]
Urgent pointer: 0

2 连接建立的超时重试

  • 第一次超时
  • 6秒后重试
  • 24秒后重试
  • ......
  • 非固定,可调整

3 最大报文段长度:MSS

  • 最大报文长度(MSS)表示TCP传往另一端的最大块数据的长度。
  • 默认536字节,超出需要分节(Segment),该值来源于IPv4的最小重组缓冲区大小(576字节),IP首部+TCP首部为40字节,所以传输数据为576-40=536字节。

4 TCP的半关闭

  • TCP提供了连接的一端在结束它的发送后还能接受来自另一端数据的能力。
  • 即我已经完成了数据传送,因此发送一个文件结束(FIN)给另一端,但我还想接收另一端发来的数据,直到它给我发来文件结束(FIN)

5 复位报文段:RST

(1)发到不存在的端口的连接请求

(2)异常终止一个连接

# 某一端直接关闭连接
Transmission Control Protocol, Src Port: 2446, Dst Port: 1883, Seq: 1, Ack: 1, Len: 0
Source Port: 2446
Destination Port: 1883
Sequence number: 1 (relative sequence number)
Acknowledgment number: 1 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x014 (RST, ACK) # 复位报文
Window size value: 0
Checksum: 0xa6e7 [unverified]
Urgent pointer: 0
  • 优点

    • 应用程序丢弃任何代发的数据并立即发送复位报文段
    • RST的接收方会区分另一端执行的是异常关闭还是正常关闭

(3)检测半打开连接

  • 半打开:一方终止,一方还不知道。
  • 出现原因:掉电(模拟机直接关闭即可)

6 同时打开

  • 双方同时执行主动打开,即每一方都发送SYN,但最终只建立了一个连接。
  • 模拟这个可以通过辣鸡VPN进行测试,如亚马逊的免费云(即往返时间比较长,便于模拟)。

7 同时关闭

  • 同时关闭与正常关闭使用的段交换数目相同。

8 TCP选项

  • 选项表结束:kind=0(1字节)
  • 无操作:kind=1(1字节)
  • 最大报文长度:kind=2(1字节),len=4(1字节),最大报文段长度(2字节)
  • 窗口扩大因子:kind=3(1字节),len=3(1字节),移位数(1字节)
  • 时间戳:kind=8(1字节),len=10(1字节),时间戳值(4字节),时间戳回显应答(4字节)
# 发送MSS
TCP Option - Maximum segment size: 1460 bytes
Kind: Maximum Segment Size (2)
Length: 4
MSS Value: 1460
# NOP
TCP Option - No-Operation (NOP)
Kind: No-Operation (1)
# 窗口扩大因子
TCP Option - Window scale: 8 (multiply by 256)
Kind: Window Scale (3)
Length: 3
Shift count: 8

三 未来计划

  • 学习TCP是为了更好地理解MQTT协议(即自顶向下的学习方式,以前自底向上学过一段时间,效果一般,因为没有应用场景)
  • TCP学完之后,将补充HTTP协议(基于TCP协议)
  • HTTP协议之后,将学习WebSocket协议,并最终回到MQTT协议(能够基于WebSocket协议进行传输)

TCP协议探究(一):报文格式与连接建立终止的更多相关文章

  1. TCP/IP 数据包报文格式(IP包、TCP报头、UDP报头)(转)

    reference:http://blog.51cto.com/lyhbwwk/2162568                    https://blog.csdn.net/wangzhen209 ...

  2. TCP协议探究(四):定时器

    1 概述 重传定时器:使用于当希望收到另一端的确认. 坚持(persist)定时器:使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口 保活(keepalive)定时器:用于检测一个空闲连接的另一 ...

  3. TCP协议探究(二):超时与重试

    1 概述 TCP提供可靠的运输层. 可靠性保证之一:确认从另一端收到的数据. 但数据和确认都有可能会丢失.TCP通过在发送时设置一个定时器来解决这种问题. 如果当定时器溢出时还没有收到确认,它就重传该 ...

  4. HTTP协议中的报文格式

    按照传输过程,HTTP 报文分为请求报文和响应报文.请求报文和响应报文的结构差不多,这里只对 HTTP 请求报文做一个总结.HTTP 请求报文由 请求行.请求头.请求体(请求数据).空行 四个部分组成 ...

  5. TCP协议探究(三):RTT、滑动窗口和阻塞处理

    1 RTT算法 1.1 概述 上一节说了重传机制需要设置一个重传超时值(RTO,Retransmission TimeOut),RTO设长了,重发太慢:设短了,可能导致包没有丢,就重发了,可能导致雪崩 ...

  6. http,tcp,udp的报文格式

    http请求报文与响应报文:https://blog.csdn.net/qq_26565861/article/details/80969960 tcp与udp报文:https://www.cnblo ...

  7. HTTP协议报文格式

    HTTP协议报文格式 接下来我们看看HTTP协议(Hypertext Transfer Protocol――超文本传输协议)浏览器端(客户端)向WEB服务器端访问页面的过程和HTTP协议报文的格式. ...

  8. TCP协议承载的DNS报文,DNS报文首部前多出两个字节的DNS报文长度字段,是何意义?

    一.TCP报文头部简介 ●源.目标端口号字段:占16比特.TCP协议通过使用"端口"来标识源端和目标端的应用进程.端口号可以使用0到65535之间的任何数字.在收到服务请求时,操作 ...

  9. TCP协议设计原理

    TCP协议设计原理 最近去了解TCP协议,发现这是一个特别值得深思的协议.在本篇博客中,不会长篇大论的给大家介绍TCP协议特点.包头格式以及TCP的连接和断开等基本原理,而是会带大家深入理解为什么要这 ...

随机推荐

  1. 如何把Java的double类型变量保留两位小数

    已知 双精度标量 f,  如果想以字符串形式输出,小数点后保留2位,可直接通过C语言的输出格式,System.out.printf("%.2f", f), 达到目的. 如果想要先转 ...

  2. HearthBuddy Ai调试实战1-->出牌的时候,少召唤了图腾就结束回合

    期望通过ai的调试,来搞明白出牌的逻辑. 55是投火无面者63是恐狼前锋34是风怒36是自动漩涡打击装置13是空灵召唤者, "LocStringZhCn": "<b ...

  3. docker下搭建owncloud

    在ubuntu下 搭建owncloud 用docker-compose启动,owncloud.yml文件内容 owncloud: image: owncloud: restart: always 开机 ...

  4. 原生js实现深复制

    function deepClone (obj) { if (obj === null) { // 如果是null则直接返回 return obj; } let copy = Array.isArra ...

  5. Maven打包将依赖的jar一同打进去

    在pom.xml文件中添加: <build> <plugins> <plugin> <artifactId>maven-assembly-plugin& ...

  6. 嵌入(embedding)层的理解

    首先,我们有一个one-hot编码的概念. 假设,我们中文,一共只有10个字...只是假设啊,那么我们用0-9就可以表示完 比如,这十个字就是“我从哪里来,要到何处去” 其分别对应“0-9”,如下: ...

  7. Grep---linux系统三剑客(一)

    grep .sed.awk被称为linux中的"三剑客". grep 更适合单纯的查找或匹配文本 sed  更适合编辑匹配到的文本 awk  更适合格式化文本,对文本进行较复杂格式 ...

  8. JS遍历数组,实现数组去重(重复的元素只保留一个)

    1.遍历数组法 它是最简单的数组去重方法(indexOf方法) 实现思路:新建一个数组,遍历去要重的数组,当值不在新数组的时候(indexOf为-1)就加入该新数组中: var arr=[2,8,5, ...

  9. pytest.mark.parametrize()参数化应用二,读取json文件

    class TestEnorll(): def get_data(self): """ 读取json文件 :return: """ data ...

  10. 【计算机】DMA原理1

    DMA原理:DMA(Direct Memory Access,直接内存存取) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依于 CPU 的大量中断负载.否则,CPU 需要从来源把 ...