一、TCP
传输控制协议 (Transmission Control Protocol),是一种面向连接的、可靠的、基于字节流的运输层通信协议。
TCP是全双工模式,所以需要四次挥手关闭连接。
二、报文数据格式
源端口号 16 bit | 目标端口号 16 bit | ||||||||||||||||||||||||||||||
序号(seq :sequence number) 32 bit | |||||||||||||||||||||||||||||||
确认号(ack :acknoledgement number) 32 bit | |||||||||||||||||||||||||||||||
首部长度 4 bit | 保留 6 bit | URG | ACK | PSH | RST | SYN | FIN | 接收窗口 16 bit | |||||||||||||||||||||||
校验和 16 bit | 紧急数据指针 16 bit | ||||||||||||||||||||||||||||||
选线(变长) | |||||||||||||||||||||||||||||||
用户数据 (变长) |
- 源端口号 (16 bit): 范围0~65535。
- 目标端口号 (16 bit): 范围0~65535。
- 序号 (32 bit):seq序号。当前数据 字节起始位置。
- 确认号 (32 bit):ack序号。也是对端下一个seq序号。
- 首部长度 (4 bit):表示头部有多个32bit,4bit最大为15,所以头部最大为32 * 15 = 480bit,即60字节
- 保留长度 (6 bit):
- URG(1 bit): 紧急。URG=1,表示发送端 优先发送报文,不再按序发送。
- ACK(1 bit): 确认。ACK=1,表示确认号有效,否则无效( 建立连接后ACK为1 )。
- PSH(1 bit): 推送。PSH=1,表示接收端 接收报文后,即使缓冲区未满也会立刻返回。
- RST(1 bit): 复位。RST=1,表示连接出现错误,必须释放重连。
- SYN(1 bit): 同步。SYN=1,表示这是一个连接请求 或 连接接收报文。
- FIN(1 bit): 终止。FIN=1,表示发送端数据已发送完毕,并要求释放连接。
- 接收窗口 (16 bit): 表示本端TCP接收缓冲区能容纳多少字节的数据,实现流量速度控制。
- 校验和(16 bit):由发送端填充,接收端执行CRC算法检验报文是否损坏。
- 紧急指针 (16 bit):配合URG,找到紧急数据的字节号(紧急数据字节号(urgSeq)=TCP报文序号(seq)+紧急指针(urgpoint)−1)
- 选项字段 (变长):
- 用户数据 (变长)
三、建立连接(三次握手)
客户端 :(1号包)可以建立连接么? [ seq=0,ack=0,len=0 ]
seq = 0 : 客户端序号:第一次的序号实际上并非为0;
ack = 0 : 由于建立连接还未完成,所以还未接收数据;
len = 0 :表示此次还未传输数据,只是建立连接。
(2号包)可以 [ seq=0 , ack=1 , len=0 ] :服务端
seq : 服务端序号,第一次的序号实际上并非为0;
ack = 1 : 表示已接收到客户端报文(0+1) ,也是客户端下一个序号Seq ( 下一份数据起始位置 )
服务端2号包 ack = 客户端1号包(seq + 1 )
len = 0 :表示此次还未传输数据,只是建立连接。
客户端 :(3号包)好的,我要开始传输数据了 [ seq=1,ack=1,len=0 ]
seq = 1 : 客户端序号,服务端2号包的ack(表示客户端本次发送数据的起始位置);
ack = 1 : 表示已接收到服务端报文( 0+1 );同时也是下一个服务端序号。
客户端3号包 ack = 服务端2号包(seq + 1 ) ;
len = 0 :表示此次还未传输数据,只是建立连接。
四、传输数据
客户端 :(4号包) 正式开始发送请求数据 [ seq=1,ack=1,len=66 ]
seq = 1 ,ack = 1:由于刚建立完连接, 没有发送和接受数据,所以还都是1。
len = 66 : 本次客户端发送的数据字节大小。
(5号包) 已经收到你的请求 [ seq=1,ack=67,len=0 ] :服务端
seq = 1: 服务端序号,是客户端4号包ack(表示服务端本次发送数据的起始位置)
ack = 67 : 表示已接收到客户端的请求数据4号包(1 + 66 ),
也是客户端下次发送数据的起始位置seq;
服务端5号包 ack = 客户端4号包(seq + len)
len = 0 : 服务端确认请求,没有发送数据
(6号包) 服务端正式返回数据 [ seq=1,ack=67,len=2233 ] :服务端
seq = 1 ,ack = 67:这时还没接收到客户端数据,所以seq和ack不变。
len=2233 : 服务端发送的数据大小。
客户端 :(7号包) 收到 [ seq = 67, ack=2234 , len=0 ]
seq = 67 : 本次客户端报文序号,也是6号包的ack。
ack = 2234 :表示已接收到 服务端6号包(1 + 2233 ) 的数据。
客户端7号包 ack = 服务端6号包(seq + len)。
五、断开连接(四次挥手)
客户端:(8号包) 我要断开连接了 [ seq = 67, ack=2234 , FIN = 1 ]
seq = 6号包ack
ack = 6号包(seql + len)
FIN = 1 :请求断开连接
(9号包) 好的 [ seq = 2234, ack = 68 ] :服务端
接收到客户端断开请求,发送确认。
9号包seq = 客户端8号包 ack
9号包ack = 客户端8号包(seq + 1)= 67 + 1
(10号包) 我也要断开连接了 [ seq = 2234, ack = 68, FIN = 1 ] :服务端
发送服务端断开请求。
由于没有接收到客户端请求,所以seq和ack不变
FIN = 1 : 请求断开连接
客户端:(11号包) 好的 [seq = 68, ack = 2235]
接收到服务端断开请求,发送确认。
11号包 seq = 10号包ack
11号包 ack = 10号包(seq + 1)= (2234 + 1)
客户端等待2MSL的时间后没有服务端收到回复,则服务端应正常关闭了,Client端关闭连接。