握手通俗理解为两个人见面Say Hai,客户端和服务端建立连接
挥手就可以理解为两个人结束会面,要Say Goodbai,客户端和服务端断开连接
要了解什么是三握四挥,必须要了解一个重要的知识点:什么是TCP报文格式,也就是三握四挥中传送的内容是什么,遇到什么格式才能触发服务端和客户端的交流。
TCP报文是TCP层传输的数据单元,也叫报文段
从上向下依次来看:
1)源端口:源端口和IP地址是标识报文的返回地址
2)目的端口:端口指明接收方计算机上的应用程序接口
TCP报头中的源端口号和目的端口号同IP数据报中的源IP与目的IP唯一确定一条TCP连接
1)序号:seq(4字节 = 32位)每一个报文都有自己的序号,这个是根据计算机自动生成的,用来唯一标识当前报文。在TCP传送的流中,每一个字节一个序号。
比如:一个报文段的序号为 300,此报文段数据部分共有 100 字节,则下一个报文段的序号为 400 。所以序号确保了 TCP 传输的有序性。
2)确认序号:(4字节 = 32位)一般用小写 ack 表示,指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。
由于首部可能含有可选项内容,因此TCP报头的长度是不确定的,报头不包含任何任选字段则长度为20字节,4位首部长度字段所能表示的最大值为1111,转化为10进制为15,15*32/8 = 60,故报头最大长度为60字节。首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。
1)URG:紧急指针标志,为 1 时表示紧急指针有效,为 0 则忽略紧急指针。
2)ACK:确认序号标志,为 1 时表示确认号有效,为 0 表示报文中不含确认信息,忽略确认号字段。
3)PSH:push 标志,为 1 表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
4)RST:重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。
5)SYN:同步序号,用于建立连接过程,在连接请求中,SYN = 1 和 ACK = 0 表示该数据段没有使用捎带的确认域,SYN = 1 和 ACK = 1 为连接应答捎带一个确认 。
6)FIN:finish 标志,用于释放连接,为 1 时表示发送方已经没有数据发送了,即关闭本方数据流。
用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小时一个16bit字段,因而窗口大小最大为65535。
此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。
紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。
在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。
便于理解图:
实际:
TCP协议是传输层的一个面向连接的安全可靠的传输协议,三次握手的机制是保证能建立一个安全可靠的连接。
(为什么两次握手不行?)以上两次握手之后,对于客户端来说已经知道,我既能给服务端发消息也能收到服务端发的消息,但是对于服务端来说,两次握手是不够的,因为,到目前为止,服务端只知道一件事情,客户端发给我的消息我能收到,我发给客户端的消息能不能收到不能确认。
通过以上三次连接,不管是客户端还是服务端,都能确认我既能给对方发消息,也能收到对方的消息,那么这个连接可以被安全的建立。
便于理解图:
实际图:
因为在这两次握手之后,对于客户端来说,发送和接收都没有问题,但是对于服务器,只知道接受没有问题,发送的消息客户端有没有收到,服务器是不知道的,因此需要第三次握手,第三次握手保证了客户端和服务端既能给对方发送消息,又能响应对方。
这是两种情况,第一种是把服务器的确认ACK和连接SYN分两次发送,这种在理论上是可行的,就好比
服务器:我在
服务器:你在吗?
但是一次性能干完的事情,非分两次,太浪费资源了。
第二种情况就是客户端再次发送确认消息,也是同理,三次握手就已经保证了双方的连接是可靠的,客户端再确认也是浪费资源
当客户端发送断开请求给服务端时(第一次挥手),服务端首先应该回复客户端确认收到(第二次挥手),但此时不确定服务端是否准备好(是否有未处理完的消息),所以应该等服务端处理好之后,再发送断开消息给客户端,告诉客户端已经准备好断开了(第三次挥手),这样客户端收到消息就会知道服务端已经准备好,可以断开,但此时客户端要给服务端发送确认收到的消息(第四次挥手),这样便确保了整个挥手断开过程顺利进行。