TCP三次握手
所谓的三次握手(three-way handshake),即建立TCP连接,也就是指在建立一个TCP连接时,需要客户端和服务端总共发送3个数据包,来确认连接建立,在socket中,这个过程由客户端执行connect()来触发。
首先我们先来看一下TCP的包结构
源端口:发起端口
目的端口:发送到的端口
序号:Sequence number(顺序号码)
确认号:Acknowledge number(确认号码)
数据偏移:由于TCP的头部的长度是不固定的,所以我们需要记录TCP的头部距离数据开始的地方有多远。
首先我们看到TCP保留标志位,有6种标示:
SYN(synchronous建立联机)
ACK(acknowledgement 确认)
PSH(push传送)
FIN(finish结束)
RST(reset重置)
URG(urgent紧急)
一般我们常用的就是SYN,.FIN,ACK
窗口:用来控制对方发送的数据量,单位为字节。TCP连接的一端根据设置的缓存空间大小确定自己的接收窗口大小,然后通知对方以确定对方的发送窗口的上限
检验和:2字节,检验和字段检验的范围包括首部和数据这两部分。在计算检验和时,要在TCP报文段的前面加上12字节的伪首部
紧急指针:2字节,紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。
选项字段:长度可变。TCP首部可以有多达40字节的可选信息,用于把附加信息传递给终点,或用来对齐其它选项。
填充字段:这是为了使整个首部长度是4字节的整数倍。
(1)第一次握手时,client将标志位SYN设置为1,随机产生一个值seq=J,并将该数据包发送给server,client进入SYN_SENT状态,等待Server确认
(2)第二次握手时,server收到数据包后由标志位SYN=1知道client请求建立连接,server将标志位SYN和ACK都设置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给client以确认连接请求,server进入SYN_RCVD状态。
(3)第三次握手时,client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK设置为1,ack=k+1,并将改数据包发给server,server检查ack是否为ack是否为K+1,ACK是否为1,如果正确则连接建立成功,client和server进入ESTABLISHED状态,完成三次握手,随后client和server之间便可以开始传输数据了。
面试题会问:
1 为什么需要三次握手,两次不可以吗?或者四五次可以吗?
我们来分析一种特殊情况,假设客户端请求建立连接,发给服务器SYN包等待服务器确认,服务器收到确认后,假如只是两次握手,服务器第二次握手时发送数据,数据从服务器出发,服务器认为已经建立连接,但是发送数据的过程中数据丢失,客户端认为连接没有建立,会进行重传,假设每次发送数据一直在丢失,客户端一直SYN,服务器就会产生多个无效的连接,占用资源,这个时候服务器可能会挂掉,这个现象就是我们听过的’‘SYN的洪水攻击’’
当然多次的握手也已经属于没有必要的连接了,三次已经达到确认的,完整的流程了,再多次的发送数据包,只会浪费服务器资源。
总结:第三次握手是为了防止,如果客户端迟迟没有收到服务器返回的确认报文,这时会放弃连接,重新启动一条新的连接请求,但是问题是:服务器不知道客户端并没有收到,所以他会收到两个连接,连接浪费资源开销,如果每次都这样,就会浪费多个资源开销。
本文在参考书籍学习视频及其各个博客后整理的学习记录,不足处还望理解。