TCP/IP协议族的传输层基础(2)——TCP协议的头部结构
TCP协议(Transmission Control Protocol,传输控制协议)
TCP协议为应用层提供可靠的、面向连接的和基于流的服务。
可靠的
- TCP采用发送应答机制(ACK),这是TCP可靠传输的关键,其他的可靠传输基本上在这基础上添加的一些方法,即发送端发送的每一个报文都必须得到对方的应答,才认为这个TCP报文段传输成功。
- TCP采用超时重传机制,发送端发送出一个TCP报文段之后启动定时器,如果在定时间内未收到应答,它将重发该报文
- TCP头部有一个32位序号,TCP协议最终都是通过IP协议发送的,IP协议到达对端之后可能是混乱的,重复的,所以有了这个序号就可以对TCP协议进行重排、整理,再交给应用层
面向连接的
- TCP协议通信的双发必须先建立连接,然后才能开始数据的读写。
- 双发都必须要为连接分配必要的内核资源,以管理连接的状态和连接上数据的传输。
- 连接完成之后,双方都必须释放连接所占用的系统资源。
- TCP的这种连接是一对一的,所以基于广播和多播(目标是多个主机地址)的应用程序不能适用于TCP协议,因此这种广播和多播的程序经常使用UDP
基于流的
- 区别于UDP的基于数据报
- 发送端应用程序执行写操作的时候,TCP内核先将其写入到发送缓冲区中,当真正要发送的时候,再将发送缓冲区中的内容分成一个或多个TCP数据报发出,这跟应用程序执行写的次数并没有直接关系(比如写了8次,结果最终只发送了一个TCP数据报)
- TCP数据报到达对端后,先被TCP内核放到了接收缓冲区中,当接收端应用程序进行读操作的时候,可以分多次读出缓冲区中的内容,也可以一次读出所有内容,这取决于缓冲区的大小,因此读操作的次数和接收到的TCP报文的数目也并没有直接的关系
下面是TCP报文的格式
- 源/目的端口号:表示数据从哪个端口来,到哪个端口去
- 32位序号/32位确认序号:发送端将发送的数据进行标号,系统随机生成一个ISN(初始序号值),后续的TCP报文段中序号值将被系统设置成ISN加上该报文段所携带数据的第一个字节在整个字节流中偏移。标的号在32位序号中,接收端确认收到的序号,将收到的序号的下一个序号通过确认序号发送(比如发送端发了1000-2000的数据,就在序号中填写ISN+1000,接收方确认应答给发送方发送确认应答2001序号,表示1000-2000的数据都接收到了)
- 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节),所以TCP头部最大长度是15*4=60,最多有60和字节(包括固定大小20个字节)。
-
6位标志位
- URG:紧急指针是否有效
- ACK:确认号是否有效
- PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
- RST:对方要求重新建立连接,携带RST标识的称为复位报文段
- SYN:请求建立连接,携带SYN标识的称为同步报文段
- FIN:通知对方,本端要关闭了,携带FIN标识的称为结束报文段
- 16位窗口大小:是TCP流量控制的一个手段,这个窗口指的是接收通告窗口。接收方将自己可以接受的缓冲区大小放入这个字段,通过ACK发送给发送端,这样发送方就可以控制自己的发送速度。
- 16位校验和:发送端填充,CRC(校验方式,完全累加)校验,接收端校验不通过,则认为数据有问题。此处检验和不包含TCP首部,也包含数据部分
- 16位紧急指针:标识哪部分数据是紧急数据
使用tcpdump抓包查看TCP报文的内容
- Flags[S]:表示该TCP报文段包含SYN标志,它是一个同步报文段,其他报文是其他标志,比如Flags[F]就是结束报文段
- seq是序号值,这个是系统随机生成的,因为这是该传输方向上的第一个报文,因此这个这就是ISN的值,并且它没有确认序号,因为对端还没有响应且这是第一个报文
- win是发送端告诉接收端自己的窗口大小。
-
options是TCP中的选项,其具体内容在方括号中。
- mss是发送端通告的最大报文段长度(Max Segment Size),这里是65495,是MTU减去了IP头部的20字节和TCP头部的20字节。
- sackok表示发送端支持并同意使用SACK选项
- TS val是发送端的时间戳
- ecr是时间戳回显应答,因为这是一次TCP通信的第一个TCP报文段,所以它针对对方的时间戳的应答为0(尚未收到对方的时间戳)
- nop是一个空操作选项
- wscale指出发送端使用的窗口扩大因子为8
接下来分析输出的字节码中属于TCP部分的信息(到第二行0001为止,前面的都是IP头部,具体什么意思还请看另一篇博客IP协议头部信息)
十六进制数 |
十进制表示 |
TCP头部信息 |
0xe740 |
59200 |
16位源端口号 |
0x0017 |
23 |
16位目的端口号 |
0xc70d9753 |
3339556691 |
32位序号 |
0x00000000 |
0 |
32位确认序号 |
0xa |
10 |
4位首部长度(10个32位) |
0x002 |
2(000000 000010 ) |
前6位保留,后6位设置SYN标记 |
0xaaaa |
43960 |
16位窗口大小 |
0xfe30 |
16位校验和 |
|
0x0000 |
16位紧急指针(这里没设置) |
剩下的都是选项部分的内容,这里我们暂时不看。