在学习TCP 三次握手四次挥手之前,让我们先来看下计算机网络分层:主要分为OSI模型和TCP/IP模型.OSI模型比较复杂且学术化,所以我们实际使用的TCP/IP模型。
// 以连接Mysql服务器为例理解这五层
// 应用层
应用层包含各种应用和服务,例如数据库访问协议(如MySQL协议)、HTTP、FTP等。
在这一层,数据库客户端应用通过MySQL协议与MySQL服务器进行通信,发送查询请求、接收查询结果等.
// 传输层
传输层包括TCP或UDP协议.
如果使用TCP,该层负责建立连接、数据的可靠传输、流量控制等。
如果使用UDP,它提供了一种更轻量级的传输,但不保证可靠性和顺序性。
// 网络层
网络层包含IP协议,负责进行逻辑寻址,例如IPv4或IPv6地址。
在连接计算机和MySQL服务器的网络中,网络层确保数据包按照源和目标IP地址的路由规则进行传输。
// 数据链路层
数据链路层包括网络适配器(网卡)和设备驱动程序。
在这一层,数据链路层负责将比特流组织成数据帧,通过MAC地址进行帧的传输,同时处理帧的错误检测与纠正。
// 物理层
物理层包含物理介质和硬件设备,例如网线、网卡等。
该层负责实际比特流的传输,确保数据能够在计算机和远端MySQL服务器之间的物理连接上可靠传输。
网络中传输的数据包由两部分组成:一部分是协议所要用到的首部,另一部分是上一层传过来的数据。
// 我们用用户客户端A发送,服务端B接收来来说明
1.客户端A会进行编码处理产生报文,交给下面的传输层.(message)
2.传输层将应用层数据封装为报文段并附加一个TCP包首部,然后交给下面的网络层.(segment)
3.网络层会将传输层传过来的数据,加上IP首部,生成IP数据报(datagram),然后交给数据链路层.
4.数据链路层将网络层传过来的数据,加上链路层首部,生成链路层帧(frame),然后传给物理层.
5.物理层将数据链路层的数据转化为比特流传输给服务端B的物理层.
6.服务端B的物理层接收到比特流,并将其转换为数据链路层能够理解的形式,也就是将比特流还原成链路层的帧.(frame)
7.服务端B的数据链路层接收到物理层的帧后,会进行解封装,去掉链路层首部,得到网络层的数据报。(datagram)
8.服务端B的网络层接收到数据链路层的数据报后,进行解封装,去掉网络层的IP首部,得到传输层的报文段。
9.服务端B的传输层接收到网络层的报文段后,进行解封装,去掉传输层的TCP包首部,得到应用层的数据。
10.最终,服务端B的应用层接收到传输层的数据后,进行解码处理,得到最初由客户端A发送的原始应用层数据。这个数据可能是一个HTTP请求、数据库查询等,根据应用层协议的不同而有所不同。
TCP(Transmission Control Protocol)是TCP/IP协议族中的一个重要协议,与上面提到的网络分层(物理层、数据链路层、网络层、传输层、应用层)密切相关。TCP协议位于传输层,承担了可靠的端到端数据传输的责任。
TCP的三次握手(Three-Way Handshake)是建立TCP连接的过程,确保通信的双方都准备好进行数据传输。这过程包括客户端和服务器之间的协商和确认。以下是TCP三次握手的具体步骤:
// 第一次握手
客户端将请求报文SYN设置为1,sequence Number(上图seq)发送给服务端,然后客户端进入SYN_SENT状态,等待服务器确认.
// 第二次握手
服务器端收到客户端的请求报文,SYN=1知道客户端请求连接,服务端应答SYN和ACk都为1,返回Acknowledgment Number(上图的acknum,即客户端发送的seq+1),然后也给服务端发送一个seq(这里是个新的数值),然后服务器进入SYN_RCVD状态.
// 第三次握手
客户端收到应答报文后,检查acknum是否是之前自己发送的seq+1,检查ACK是否为1,如果都正确,则发送ACK位置为1,给服务端发送的seq+1返回。服务端收到报文,如果都正确,则连接建立成功.客户端服务端都进入ESTABLISHED状态。完成三次握手.
// 总结
1.客户端发送syn=1,seq1 -> 服务端
2.服务端返回ack=1,syn=1,acknum = seq1+1,seq2 -> 客户端
3.客户端返回ack=1,acknum = seq2+1 -> 服务端
针对三次握手的问题
// 为什么要三次握手?
主要是为了数据传输的可靠性,而三次握手是保证数据可靠传输又能提高传输效率的最小次数.在传输过程中都必须维护一个序列号,标识发送出去的数据包哪些已经被对方收到.
假如:客户端发送数据包(假设到校为10byte),同时发送一个序列号为1000,那么服务端接收到数据包之后,会返回一个确认号1010(1000+10),表明发送下一个序列号从1011开始.
// 为什么不是两次?
假设只有2次握手,客户端发送SYN,服务端返回SYN和ACK,然后客户端突然失效.此时服务器认为连接已经建立,这样如果后面有其他的客户端使用相同的ip地址和端口号连接,服务器可能会误以为是之前的请求,导致连接混乱。
// 以客户端主动关闭连接为例
// 第一次挥手
客户端决定关闭连接,向服务端发送一个带有FIN标志的TCP数据包,表示客户端不再发送数据。进入入FIN-WAIT-1状态
// 第二次挥手
服务端收到客户端的FIN请求后,发送一个带有ACK标志的TCP数据包,表示已经收到了关闭请求。此时,服务端进入CLOSE_WAIT状态,等待可能还在传输的客户端的数据传输完成。
// 第三次挥手
当服务端也准备好关闭连接时,发送一个带有FIN标志的TCP数据包给客户端,表示服务端不再发送数据。
// 第四次挥手
客户端收到服务端的FIN请求后,发送一个带有ACK标志的TCP数据包,表示已经收到了服务端的关闭请求。此时,客户端进入TIME_WAIT状态,等待可能未到达的服务端的最终确认.
针对四次挥手的问题
// 为什么TCP的挥手需要四次?
TCP是全双工的连接,必须两端同时关闭连接,连接才算真正关闭。
挥手时可能有数据在传输: 在挥手的时候,客户端和服务端都可能还有未发送完的数据。挥手过程需要等待这些数据传输完成,才能安全关闭连接。
// 为什么需要TIME-WAIT状态?
在网络中,ACK确认可能因为延迟而无法及时到达。通过等待一段时间,服务端可以处理可能的 ACK 延迟,确保客户端已经完全接收到了服务端的关闭请求。
三次握手用于建立连接,确保双方都愿意通信;四次挥手用于关闭连接,保证双方都能安全、可靠地关闭连接。在这些过程中,序列号、确认号、状态转换等都起到关键作用,确保了连接的可靠性和稳定性。