TCP协议解读
一、TCP头部解析:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCP Header Format
二、 TCP建立连接和断开连接的过程:
![](https://i-blog.csdnimg.cn/blog_migrate/69101b1bacf4c346ba12376dcfbaf7df.png)
-
三次握手:
建立一个TCP连接的时候,会发生三路握手,详细的过程描述- (建立连接前,Server端必须准备好接受外来的连接,这通常是调用 socket、bind、listen三个函数来完成)
- Client发起连接请求(这通常是通过socket、connect函数来完成的)将标志位SYN置为1,随机产生一个值seq=x,并将该分节发送给Server,Client进入SYN_SENT状态,等待Server确认。
- Server收到数据包后由标志位SYN=1知道Client请求建立连接;Server将标志位ACK置为1,确认号ACK=x+1;同时将ACK标志位置1并随机产生一个值seq=y;然后将该分节发送给Client以确认连接请求,Server进入SYN_RCVD状态。
- Client收到确认后,检查ACK是否为x+1,ACK是否为1;如果正确将标志位ACK置为1,ACK=y+1,并将该分片发送给Server;Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功;Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
-
四次挥手:
由于TCP连接时全双工的,因此每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。- 数据传输结束后,客户端的应用进程主动关闭(通常是调用close函数) ,并停止发送数据,客户端进入FIN_WAIT_1状态,此时客户端依然可以接收服务器发送来的数据。
- 服务器接收到FIN后,发送一个ACK给客户端,确认序号为收到的序号+1,服务器进入CLOSE_WAIT状态。客户端收到后进入FIN_WAIT_2状态。
- 当服务器没有数据要发送时,服务器发送一个FIN报文,此时服务器进入LAST_ACK状态,等待客户端的确认
- 客户端收到服务器的FIN报文后,给服务器发送一个ACK报文,确认序列号为收到的序号+1。此时客户端进入TIME_WAIT状态,等待2MSL(MSL:报文段最大生存时间),然后关闭连接。
-
Q&A:为什么必须是三次握手?
- 两次不可以:tcp是全双工通信,两次握手只能确定单向数据链路是可以通信的,并不能保证反向的通信正常
- 不用四次:本来握手应该和挥手一样都是需要确认两个方向都能联通的,本来模型应该是:
- 客户端发送syn0给服务器
- 服务器收到syn0,回复ack(syn0+1)
- 服务器发送syn1
- 客户端收到syn1,回复ack(syn1+1)
- 因为tcp是全双工的,上边的四部确认了数据在两个方向上都是可以正确到达的,但是2,3步没有没有上下的联系,可以将其合并,加快握手效率,所有就变成了3步握手。
- 三次握手可以防止已经失效的连接请求报文突然又传输到服务器端导致的服务器资源浪费。例如,客户端先发送了一个SYN,但是由于网络阻塞,该SYN数据包在某个节点长期滞留。然后客户端又重传SYN数据包并正确建立TCP连接,然后传输完数据后关闭该连接。该连接释放后失效的SYN数据包才到达服务器端。在二次握手的前提下,服务器端会认为这是客户端发起的又一次请求,然后发送SYN ,并且在服务器端创建socket套接字,一直等待客户端发送数据。但是由于客户端并没有发起新的请求,所以会丢弃服务端的SYN 。此时服务器会一直等待客户端发送数据从而造成资源浪费。
-
Q&A为什么是四次挥手
由于连接的关闭控制权在应用层,所以被动关闭的一方在接收到FIN包时,TCP协议栈会直接发送一个ACK确认包,优先关闭一端的通信。然后通知应用层,由应用层决定什么时候发送FIN包。应用层可以使用系统调用函数read==0来判断对端是否关闭连接。
TCP保证可靠性措施
-
序列号、确认应答、超时重传
- 数据到达接收方,接收方需要发出一个确认应答,表示已经收到该数据段,并且确认序号会说明了它下一次需要接收的数据序列号。
- 如果发送发迟迟未收到确认应答,那么可能是发送的数据丢失,也可能是确认应答丢失,这时发送方在等待一定时间后会进行重传。这个时间一般是2*RTT(报文段往返时间)+一个偏差值。
-
窗口控制与高速重发控制/快速重传(重复确认应答)
- TCP会利用窗口控制来提高传输速度,意思是在一个窗口大小内,不用一定要等到应答才能发送下一段数据,窗口大小就是无需等待确认而可以继续发送数据的最大值。
- 如果不使用窗口控制,每一个没收到确认应答的数据都要重发。
- 使用窗口控制,如果数据段1001-2000丢失,后面数据每次传输,确认应答都会不停地发送序号为1001的应答,表示我要接收1001开始的数据,发送端如果收到3次相同应答,就会立刻进行重发;
- 但还有种情况有可能是数据都收到了,但是有的应答丢失了,这种情况不会进行重发,因为发送端知道,如果是数据段丢失,接收端不会放过它的,会疯狂向它提醒…
-
拥塞控制
- 如果把窗口定的很大,发送端连续发送大量的数据,可能会造成网络的拥堵(大家都在用网,你在这狂发,吞吐量就那么大,当然会堵),甚至造成网络的瘫痪。所以TCP在为了防止这种情况而进行了拥塞控制。
- 慢启动:定义拥塞窗口,一开始将该窗口大小设为1,之后每次收到确认应答(经过一个rtt),将拥塞窗口大小*2。
- 拥塞避免:设置慢启动阈值,一般开始都设为65536。拥塞避免是指当拥塞窗口大小达到这个阈值,拥塞窗口的值不再指数上升,而是加法增加(每次确认应答/每个rtt,拥塞窗口大小+1),以此来避免拥塞。
- 将报文段的超时重传看做拥塞,则一旦发生超时重传,我们需要先将阈值设为当前窗口大小的一半,并且将窗口大小设为初值1,然后重新进入慢启动过程。
- 快速重传:在遇到3次重复确认应答(高速重发控制)时,代表收到了3个报文段,但是这之前的1个段丢失了,便对它进行立即重传。然后,先将阈值设为当前窗口大小的一半,然后将拥塞窗口大小设为慢启动阈值+3的大小。
- 这样可以达到:在TCP通信时,网络吞吐量呈现逐渐的上升,并且随着拥堵来降低吞吐量,再进入慢慢上升的过程,网络不会轻易的发生瘫痪。
TCP的模型,状态转移
- 四层TCP/IP模型如下:
![](https://i-blog.csdnimg.cn/blog_migrate/76a04d68e72614bc1112c9bbd9b7c4d3.png)
+---------+ ---------\ active OPEN
| CLOSED | \ -----------
+---------+<---------\ \ create TCB
| ^ \ \ snd SYN
passive OPEN | | CLOSE \ \
------------ | | ---------- \ \
create TCB | | delete TCB \ \
V | \ \
+---------+ CLOSE | \
| LISTEN | ---------- | |
+---------+ delete TCB | |
rcv SYN | | SEND | |
----------- | | ------- | V
+---------+ snd SYN,ACK / \ snd SYN +---------+
| |<----------------- ------------------>| |
| SYN | rcv SYN | SYN |
| RCVD |<-----------------------------------------------| SENT |
| | snd ACK | |
| |------------------ -------------------| |
+---------+ rcv ACK of SYN \ / rcv SYN,ACK +---------+
| -------------- | | -----------
| x | | snd ACK
| V V
| CLOSE +---------+
| ------- | ESTAB |
| snd FIN +---------+
| CLOSE | | rcv FIN
V ------- | | -------
+---------+ snd FIN / \ snd ACK +---------+
| FIN |<----------------- ------------------>| CLOSE |
| WAIT-1 |------------------ | WAIT |
+---------+ rcv FIN \ +---------+
| rcv ACK of FIN ------- | CLOSE |
| -------------- snd ACK | ------- |
V x V snd FIN V
+---------+ +---------+ +---------+
|FINWAIT-2| | CLOSING | | LAST-ACK|
+---------+ +---------+ +---------+
| rcv ACK of FIN | rcv ACK of FIN |
| rcv FIN -------------- | Timeout=2MSL -------------- |
| ------- x V ------------ x V
\ snd ACK +---------+delete TCB +---------+
------------------------>|TIME WAIT|------------------>| CLOSED |
+---------+ +---------+
TCP Connection State Diagram
-
连接过程在生存时间内经过一系列的状态。LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT,和最后的虚构状态CLOSED。CLOSED是虚构的因为处于CLOSED状态的时候已经没有TCB,也就是说没有连接。
- LISTEN - 等待从任何远端TCP和端口的连接请求
- SYN-SENT -发送完一个连接请求后等待一个匹配的连接请求
- SYN-RECEIVED - 发送连接请求并且接收到匹配的连接请求以后等待连接请求确认
- ESTABLISHED - 表示一个打开的连接,接收到的数据可以被投递给用户。连接的数据传输阶段的正常状态。
- FIN-WAIT-1 - 等待远端TCP的连接终止请求,或者等待之前发送的连接终止请求的确认
- FIN-WAIT-2 - 等待远端TCP的连接终止请求
- CLOSE-WAIT - 等待本地用户的连接终止请求
- CLOSING - 等待远端TCP的连接终止请求确认
- LAST-ACK - 等待先前发送给远端TCP的连接终止请求的确认(包括它字节的连接终止请求的确认)
- TIME-WAIT - 等待足够的时间过去以确保远端TCP接收到它的连接终止请求的确认
- CLOSED - 不在连接状态
-
TCP连接响应不同的事件从一个状态过渡到另一个状态。事件是用户调用,OPEN,SEND,RECEIVE,CLOSE,ABORT,和STATUS;到来的分片,特别是那些包含SYN,ACK,RST和FIN标志的分片;超时。
三、OSI七层模型和TCP/IP四层模型
- 物理层: 通过媒介传输比特,确定机械及电气规范,传输单位为bit,主要包括的协议为:IEE802.3 CLOCK RJ45
- 数据链路层: 将比特组装成帧和点到点的传递,传输单位为帧,主要包括的协议为MAC VLAN PPP
- 网络层:负责数据包从源到宿的传递和网际互连,传输单位为包,主要包括的协议为IP ARP ICMP
- 传输层:提供端到端的可靠报文传递和错误恢复,传输单位为报文,主要包括的协议为TCP UDP
- 会话层:建立、管理和终止会话,传输单位为SPDU,主要包括的协议为RPC NFS
- 表示层: 对数据进行翻译、加密和压缩,传输单位为PPDU,主要包括的协议为JPEG ASII
- 应用层: 允许访问OSI环境的手段,传输单位为APDU,主要包括的协议为FTP HTTP DNS