TCP协议
TCP(Transmission Control Protocol)
面向连接的,可靠的,基于字节流的传输通信协议
特点:
-
基于连接的:数据传输之前需要建立连接
-
全双工:双向传输
TCP全双工:客户端可以想服务器端发送数据,但服务器端也可以主动向客户端发送数据
-
字节流:不限制数据大小,打包成报文段,保证有序接收,重复报文自动丢弃
TCP协议传输数据时,不会一次性全传输,会进行切分,会切成一个个的TCP的分片再进行传输,但在传输中,有很多的路线进行传输,所以数据是有可能是乱序的,在接收端需要进行重排序
-
流量缓冲:解决双方处理能力的不匹配
在数据通信之前,在TCP三次握手时,客户端和服务器双方都会创建一个缓冲区
-
可靠的传输服务:保证可达,丢包时通过重发机制实现可靠性
-
拥塞控制:防止网络出现恶性拥塞
当网络环境比较差时,发送的报文大小就会缩减,速率也会减小
TCP连接管理
1.TCP连接:四元组[源地址,源端口,目的地址,目的端口]
只要四个元素的组合中有一个元素不一样,那就可以区别不同的连接,比如:
你的IP地址是11.1.2.3, 在8080端口监听
那么当一个来自 22.4.5.6 ,端口为5555的连接到达后,那么建立的这条连接的四元组为
(11.1.2.3, 8080, 22.4.5.6, 5555)
这时,假设上面的那个客户(22.4.5.6)发来第二条连接请求,端口为6666,那么,新连接的四元组为
(11.1.2.3, 8080, 22.4.5.6, 6666)
那么,你主机的8080端口建立了两条连接;
但是,此时上面的那个客户(22.4.5.6)发来的第三条连接请求的端口如果为5555或6666的新连接,那么由于无法区分于上面两条连接,那么第三条连接的请求就无法建立
tcp/udp一般采用五元组来定位一个连接:
src_ip, src_port, dest_ip, dest_port, protocol_type
2.确认连接:TCP三次握手
- 同步通信双方初始序列号(ISN,initial,sequence,number)
- 协商TCP通信参数(MSS,窗口信息,指定校验和算法)
Source port(源端口):发送端一般时自动生成的。
Dest port(目的端口):在进行三次握手之前必须要知道目的端口时多少,一般web服务器是80端口
sequence/Acknewledgment number(序列号):用来保证可靠性传输的
Header length:首部长度
SYN:报文的标识,当SYN=1时,表示当前报文是建立连接的报文
ACK:报文的标识,当ACK=1时,表示响应的报文,可用于握手的报文已经到达
URG:报文的标识,表示该报文要优先处理
FIN:报文的表示,表示关闭连接的报文
Receive Window:表示当前可以接收数据大小的窗口的值
Options:表示可选参数
Data:表示真实的业务数据
TCP三次握手过程:
第一次握手:
1.首先服务器会进入listen状态,去监听某一个端口
2.客户端发送请求前,创建一个数据结构,存储发送端口
3.客户端会发送SYN seq(初始序列号,存储在包头的序列号(Sequence Number))=x报文,客户端就会进入一个SYN-SENT的状态
第二次握手:
1.服务器收到SYN报文后,服务器端也会在本地创建一个数据结构(包括:连接相关的信息包含缓存的信息)
2.会给客户端返回一个ACK的一个确认信息,以及一个seq=y的一个序列号,SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的IS N(初始序列号)加1以.即X+1。客户端会进入一个ESTABUSHED的状态,说明连接已经建立
第三次握手:
1.客户端接收到发送的响应报文后,再次方式确认报文(ASK),SYN标志为为0,ACK标志为为1,并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.服务器接收该序列号
如图就是三次握手的一个过程:
图中Flags[S.],中括号中的S代表SYN,S后的点,代表ACK
TCP内核处理情况:
当内核收到SYN请求时,该请求会进入到SYN队列,在收到SYN请求后,会立即返回SYN/ACK的响应报文给客户端后进行等待,客户端会发送一个ACK的请求,在收到ACK后,会将之前带SYN队列的SYN请求出队后入队到ACCEPT队列,这时SYN队列处于一个SYN_RECEIVEOD的状态,这时连接建立了,通常情况有一个应用程序会进行一个堵塞的等待,等待accept()的一个连接,之后就可以进行双向的数据通信了
3.关闭连接:TCP四次挥手
第一次挥手:A数据传输完毕需要断开连接,A的应用进程向其TCP发出连接释放报文段(FIN = 1,序号seq = u),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1状态,等待B的确认。
第二次挥手:B收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),B进入CLOSE-WAIT关闭等待状态,此时的TCP处于半关闭状态,A到B的连接释放。而A收到B的确认后,进入FIN-WAIT-2状态,等待B发出的连接释放报文段。
第三次挥手:当B数据传输完毕后,B发出连接释放报文段(FIN = 1,ACK = 1,序号seq = w,确认号ack=u+1),B进入LAST-ACK(最后确认)状态,等待A 的最后确认。
第四次挥手:A收到B的连接释放报文段后,对此发出确认报文段(ACK = 1,seq=u+1,ack=w+1),A进入TIME-WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,A才进入CLOSE状态。
等待2MSL原因:
1.保证A发送的最后一个ACK报文段能够到达B,保证A、B正常进入CLOSED状态。
这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,B超时重传FIN+ACK报文段,A能2MSL时间内收到这个重传的FIN+ACK报文段,接着A重传一次确认,同时重启2MSL计数器,2MSL时间后A和B进入CLOSE状态,如果A在TIME-WAIT状态时接收到B的FIN+ACK报文段之后向B发出确认报文段,而不再确认B是否收到立即进入CLOSED状态,如若B并没有正常收到A 的确认报文段,则B无法正正常进入到CLOSED状态。
2.防止“已经失效的连接请求报文段”出现在本连接中。
A在发送完最后一个ACK报文段并经过2MSL,会使本次连接持续时间内所有产生的报文段消失,保证在下一次新连接中不会出现旧连接遗留的请求报文段。
确认报文段,则B无法正正常进入到CLOSED状态。
2.防止“已经失效的连接请求报文段”出现在本连接中。
A在发送完最后一个ACK报文段并经过2MSL,会使本次连接持续时间内所有产生的报文段消失,保证在下一次新连接中不会出现旧连接遗留的请求报文段。