本文属临时记录,仅供自己学习使用。如有错误,请勿怪罪。后期复习会不断订正。
TCP头部信息
字段 | 功能 |
---|---|
源端口号(16bit) | 发送方端口号 |
目的端口号(16bit) | 接收方端口号 |
序列号(32bit) | TCP传送的字节流数据每一个字节都是顺序编号的,序列号就是当前的TCP报文首字节的序号 |
确认号(32bit) | 接收方期望的回复报文中数据段首字节的序号 |
首部长度(4bit) | TCP报文首部的长度 |
URG(1bit) | URG=1,表明报文数据为紧急数据,无需在发送缓存中等待排队,直接发送 |
ACK(1bit) | ACK=1 时确认号有效 |
PSH(1bit) | PSH=1,将接收缓存中的数据立即向上(应用层)交付 |
RST | 复位,重新建立连接 |
SYN | SYN=1,表明TCP报文是一个连接请求 |
FIN | FIN=1,表明报文是断开连接请求 |
窗口大小(16bit) | 接收方可以接收的数据量 |
TCP校验和 | |
紧急指针 | URG=1时,指出紧急数据的字节数 |
三次握手
Round 1:
客户端发送TCP请求报文,报文不包含应用层数据。设置SYN=1,此时因为报文未携带数据,随机生成一个序列号x
Round 2:
首先收到TCP请求后,服务器为TCP连接分配缓存和变量。
然后,向客户端发送确认报文,在确认报文中,SYN=1,ACK=1表示这是一个确认报文,保证确认号有效。因为此时并未携带回复数据,随机生成一个序列号seq=y。并且因为客户端的请求报文中序列号seq=x,按理来讲下一次应该传输序列号seq=x+1的数据,所有服务器设置确认号ack=x+1;
Round 3:
首先,收到服务器的确认报文,证明服务器收到了请求可以建立连接,所以需要为TCP连接分配缓存和变量。
然后向服务器返回对确认报文的确认,设置SYN=0,ACK=1,seq=x+1,ack=y+1
序列号:我发出的报文首字节序号
确认号:下一次我想收到的序号,并且确认前面的数据我收到了
为什么要三次握手?
假设一个情景:客户端发出了一个建立连接的请求,但是由于网络原因在网络上延迟了,但是客户端在一定时间没有收到服务器的回复,就会重新发送请求,这时又和服务器建立了连接,但是当这次连接断开后,第一次发的请求到达了服务器,这是服务器以为客户端又在请求连接。
假如没有三次握手,服务器立马建立连接,但是此时客户端因为未发出请求不会理会服务器的回复,此时服务器建立了连接等于在白白耗费资源。
四次挥手
连接的任何一方都可以终止连接。下面以客户端请求断开连接为例子:
Round 1:
客户端发送连接释放报文并停止发送数据,FIN=1,ack=u,客户端主动关闭TCP连接
Round 2:
服务端回复确认报文,因为是确认报文所有ACK=1,ack=u+1,客户端到服务器这个方向的连接就关闭了,TCP连接进入半关闭状态。
Round 3:
服务端继续发送数据,直到发送数据完成,并且此时发出的数据仍然会收到回复。
Round 4:
当发送完成后,服务器发出FIN=1的关闭连接的报文。在收到客户端的回复报文后,TCP连接完全断开。
为什么要四次挥手?
因为TCP连接时全双工的,能在两个方向上独立传输数据,因此每一方都需要单独进行关闭连接,在发送的一方还没有发送完数据的情况下就会形成半关闭状态。收到一个FIN只意味着在这一方向上没有数据流动。一个 TCP连接在收到一个 F I N后仍能发送数据。
要单独进行关闭连接,在发送的一方还没有发送完数据的情况下就会形成半关闭状态。收到一个FIN只意味着在这一方向上没有数据流动。一个 TCP连接在收到一个 F I N后仍能发送数据。
忽略掉客户端释放连接后,服务器还在发送数据的过程,还是遵循三次握手的道理。 当释放连接的时候,必须收到对方的确认报文,否则不会释放连接。