在计算机网络通信中,握手是常见的通信协议,TCP通信中的握手需要发送和接收方相互确认,并建立有效的连接。握手包就是发送和接收方之间交流的格式,它包含了通信双方共同协商好的约定,以便正常地进行数据传输。
握手包格式涵盖了TCP头部和TCP数据,包括源端口和目的端口号、TCP的序号和确认号、TCP的标志位及其对应的含义等内容。
标准的握手包格式由TCP三次握手和四次挥手的交互组成:
TCP三次握手过程:
① 客户端发送SYN分节(SYN=1)到服务器,并指明客户端的初始化序列号ISN(序列号随机生成,防止攻击);
② 服务器收到客户端的SYN分节后,必须确认(ACK=1),发送一个SYN分节,即SYN/ACK分节,其确认号为客户端的ISN+1,同时随机生成自己的初始化序列号ISS,并将其加入到ISN中,所以该分节也包含数据(ISS);
③ 客户端收到服务器的SYN/ACK分节,确认(ACK=1)其收到,并发送确认(ACK)分节,该分节的序列号为服务器的ISN+1,确认号为服务器发来的SYN分节的序列号+1。
这样,在三次握手过程中,客户端和服务器各发送了一个SYN分节和一个ACK分节,客户端和服务器都能保存对方的序列号,这样每个分节的完整性都能得到保证。
TCP四次挥手过程:
① 客户端向服务器发送FIN分节,并且停止发送数据,等待服务器的回应;
② 服务器收到客户端的FIN分节后,发送ACK确认分节给客户端,并进入CLOSE_WAIT状态,但仍然可以发送最后的数据包;
③ 当服务器最后一个数据包发送完毕后,关闭写操作,向客户端发送FIN分节,告诉客户端可以关闭了;
④ 客户端收到服务器的FIN分节后,发送ACK确认分节给服务器,然后进入TIME_WAIT的状态,等待2MSL(最长报文段寿命)后,如果还没有收到服务器的回复,则认为服务器已经关闭,客户端关闭连接。
① 源端口:数据流发送端口的TCP端口号,该号用户在接收到的数据流中通知接收方所要接收该数据流的进程;
② 目的端口:数据流接收端口的TCP端口号,接收方通过该端口接收发送者的数据流;
③ 序列号:第一个字节的序列号,用于对每个发送的MSS(最大报文长度)进行编号,发送方需要每次将发送的MSS进行累加;
④ 确认号:期望接收下一个序列号的值;
⑤ 数据偏移:用来表示TCP头部有多少个32位的字,实际上它也是一个指针,指向TCP头部结束位置;
⑥ 保留:保留字段
⑦ 标识位:用于表示TCP报文的状态和控制;
⑧ 窗口大小:{@link https://baike.baidu.com/item/TCP%E7%AA%97%E5%8F%A3/927044?fr=aladdin}TCP窗口大小,即可接收的运输数据的字节数上限;
⑨ 校验和:用于检验是否收到的不是伪造的包;
⑩ 紧急指针:告诉接收方应该从哪里开始应答数据;
⑪ 选项:按字节描写的可变长度的可选字段,选项字段是可选的,但当它出现时,它必须放在头部的末尾。选项字段包括最大段大小(MSS)、时间戳(timstamp)、无操作等。
虽然标准的握手包格式保证了TCP的正确传输,但因为每个握手包中都包含了TCP的标准头部,所以TCP的首部量就成了无法避免的负担,对网络的带宽和延迟都有一定的影响。因此,为了优化握手包在网络传输中的性能,可以采取一些手段:
① 压缩首部:对TCP的头部进行压缩,减少首部大小,例如SACK(选择性确认)可用于减少窗口扫描的次数;
② TFO(TCP Fast Open ):通过使用缓存来减少握手的回合数,减少握手延迟;
③ 0-RTT(Zero Round-Trip Time):该技术可以减少握手的回合次数,并加快TCP连接的建立。