Skip to main content

TCP协议

网络协议分层:

应用层(HTTP、DNS、DHCP...)
传输层(UDP协议、TCP协议)
网络层(IP协议)
链路层(以太网协议,依靠mac地址)
物理层(网线,光线...010101)

  • 以太网协议(Ethernet)规定电子信号如何组成数据包,解决子网内部的点对点通信
  • IP协议定义了一套地址规则,可以连接多个局域网

但是IP协议并不保证数据包的完整。如果丢包了,就需要TCP协议来发现丢了那个包,重新发送这个包

数据包大小

以太网数据包负载是1500字节,TCP数据包的负载在1400字节左右

数据包拆分编号

一次性发送大量数据,必须拆分成多个包。比如10MB的文件需要发送7100多个包

  • 发送的时候,TCP协议给每个包编号
  • 第一个包编号是个随机数,假设是1号包,他的负载长度为100字节,那么下一个包的编号为101
  • 每一个包都可以得到自身编号,以及自身编号加上自身负载长度得到下一个包的编号

数据包组装

收到TCP数据包之后,组装还原是操作系统完成的。按照上面拆分的顺序去组装

TCP数据包有一个端口参数,用来指定转交给监听该端口的应用程序

TCP没有机制表示原始文件的大小,这个由应用层的协议来规定。

比如

  • HTTP协议的头信息Content-Type,用来表示信息的大小。
  • 浏览器根据Content-Type字段读出一段段的数据。
  • 那么,一次TCP通信,可以包含多个HTTP通信

慢启动

为了做到效率与可靠性的统一,设计了慢启动的机制。

一开始发送慢,不丢包就加速,丢包就降速.

不论带宽多好,都从10个数据包开始试,然后达到最高速率

TCP标志位

SYN -- synchronous 建立联机

ACK -- acknowledgment 确认序号有效

PSH -- push 传送,接收方将报文交给应用层

FIN -- finish 结束,释放连接

RST -- reset 重置连接

URG -- urgent 紧急指针


Sequence number -- 顺序号码

Acknowledge number -- 确认号码

ACK

接收方没收到两个TCP数据包,就要发送一个确认(acknowledgement)消息

ACK携带两个信息

期待要收到下一个数据包的编号

接收方的接收窗口的剩余容量

实际上TCP的通信是双向的,双方都需要发送ACK

不要被这个图片误导,双方的第一次给数据包,他们的seq都是随机生成的。

对于单向来说:

第一次: Seq=1; length=100;Ack=1

第二次:Seq=100+1; length= 50;Ack=对方第一次返回的Seq+length

第三次:Seq=101+50; length=200;Ack=对方第二次返回的Seq+length

数据包遗失处理

如果下一个数据包没有收到,那么ACK的编号就不会变

如果发送方收到了3个连续的重复ACK,或者超时收到ACK,就会确认这个包丢了,重新发送

这里关于2号包重发后,3、4、5号包是否重发,涉及到TCP的版本。

现阶段的是,3、4、5号包不会重发。接收到2号包后,将会返回5号包后的ack,然后接着发6号包。

三次握手

目的

同步连接双方的序列号和确认号并交换 TCP 窗口大小信息。

直白理解

A > B:我要对你讲话,你能听到么

B > A:我能,我也要对你讲话,你能听到么

A > B:我也能

状态

SYN_SEND

SYN_RECV

ESTABLISHED

理解

  • 第一次握手:主机A发送位码SYN=1,随机生成seq number=x,将这个数据包发送给主机B
  • 第二次握手:主机B收到SYN=1,确认了联机信息,发送ack number = x+1SYN=1ACK=1,随机生成seq number=y。此时主机A进入ESTABLISHED已确认状态
  • 第三次握手:主机A收到信息,确认主机B的ack number =? seq number+1,且ACK =? 1。就在发送ack number = y+1 ACK = 1 seq number = x+1。此时主机B进入ESTABLISHED状态

例子

IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836 IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837 IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1

DDOS攻击 - SYN Flood攻击

伪造大量不存在的IP,向服务器发送SYN包,服务器回复确认包,进入SYN_RECV状态。(此时TCP连接为半连接状态half-open- connect)

由于源地址不存在,服务器会不断的重发包直到超时。一直占用队列。

四次挥手

因为TCP连接是双全工的,每一方都要单独关闭。

一方发送FIN,终止连接,不再传送数据,另一方可以继续发送数据,直到他也发送FIN

理解

  • 第一次挥手:主机A发送FIN=1 seq number=x。主机A进入 FIN_WAIT_1状态
  • 第二次挥手:主机B收到FIN=1 ,返回确认包ACK=1 ack number = x + 1 seq number=y 。主机B进入CLOSE_WAIT状态。主机A进入FIN_WAIT_1状态。
  • 第三次挥手:主机B发送FIN=1 ACK=1 seq number = z ack number = x + 1。主机B进入LAST_ACK状态
  • 第四次挥手:主机A收到FIN=1,发送了ACK=1 seq number = x+1 ack number = z + 1,立刻进入TIME_WAIT状态,等带2MSL进入CLOSED状态。主机B收到立即进入CLOSED状态。

为什么是四次挥手

收到FIN时,表示对方不再发送数据了,但还可以接收数据。自己这边,可能还有部分数据没有给玩。

由于ACK报文,和FIN报文基本都是分开发的

第二次挥手给ACK

第三次挥手给FIN + ACK