TCP协议三次握手

一、简介

所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。这个过程是发生在客户端调用connect()函数,服务器在调用accept()函数接收的时候。

二、一些概念

ACK: ACK (Acknowledge character)即是确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误。
在TCP/IP协议中,如果接收方成功的接收到数据,那么会回复一个ACK数据。通常ACK信号有自己固定的格式,长度大小,由接收方回复给发送方。
在TCP连接中,ACK的值是等待接收的数据包的序列号。

ACK的值 表示的是期望的对方(接收方)的下一次sequence number是多少。注意,SYN/FIN的传输虽然没有data,但是会让下一次传输的packet seq增加一,但是,ACK的传输,不会让下一次的传输packet加一。

SYN:同步序列编号(Synchronize Sequence Numbers)。是TCP/IP建立连接时使用的握手信号。在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN+ACK应答表示接收到了这个消息,最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。

Seq: (Sequence Number)即是序列号,这是为了连接以后传送数据用的。表示的是我方(发送方)这边,这个packet的数据部分的第一位应该在整个data stream中所在的位置。(注意这里使用的是“应该”。因为对于没有数据的传输,如ACK,虽然它有一个seq,但是这次传输在整个data stream中是不占位置的。所以下一个实际有数据的传输,会依旧从上一次发送ACK的数据包的seq开始)。

这三者的联系:seq是序列号,这是为了连接以后传送数据用的,ack是对收到的数据包的确认,值是等待接收的数据包的序列号。
在第一次消息发送中,客户端随机选取一个序列号作为自己的初始序号发送给服务器;第二次消息服务器使用ack对客户端的数据包进行确认,因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1,同时服务器告诉客户端自己的初始序列号,就是seq=y;第三条消息客户端告诉服务器收到了服务器的确认消息并准备建立连接,客户端自己此条消息的序列号是x+1,所以seq=x+1,而ack=y+1是表示客户端正准备接收服务器序列号为y+1的数据包。
seq是数据包本身的序列号;ack是期望对方继续发送的那个数据包的序列号。

三、连接过程

在这里插入图片描述

在这里插入图片描述

四、使用wireshark分析过程

我们用wireshark实际分析下三次握手的过程。 打开wireshark, 打开浏览器输入 http://www.cr173.com 在wireshark中输入http过滤, 然后选中GET /tankxiao HTTP/1.1的那条记录,右键然后点击"Follow TCP Stream", 这样做的目的是为了得到与浏览器打开网站相关的数据包,将得到如下图
在这里插入图片描述
图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。

第一次握手数据包
客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图
在这里插入图片描述
第二次握手的数据包

服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图

在这里插入图片描述
第三次握手的数据包
客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:
在这里插入图片描述

### TCP协议三次握手过程详解 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层协议。为了确保数据传输的可靠性,TCP在建立连接时采用了一种称为“三次握手”(Three-Way Handshake)的机制。该机制用于在客户端和服务器之间同步序列号并确认彼此的发送和接收能力,从而确保连接的可靠性。 #### 三次握手的详细过程 1. **第一次握手** 客户端发送一个SYN(同步)标志位为1的TCP段,表示请求建立连接。该段中包含客户端选择的初始序列号(Sequence Number = x)。此时,客户端进入SYN_SENT状态。 例如:`SYN = 1, Sequence Number = 2322326583` [^2]。 2. **第二次握手** 服务器收到SYN段后,会以自己的SYN段作为响应,并且设置ACK(确认)标志位为1,表示确认收到客户端的SYN请求。服务器会在该段中包含自己的初始序列号(Sequence Number = y),同时将确认号(Acknowledgment Number)设置为客户端的序列号加1(x + 1)。此时,服务器进入SYN_RCVD状态。 例如:`SYN = 1, Sequence Number = 3573692787; ACK = 1, Acknowledgment Number = 2322326583 + 1` [^2]。 3. **第三次握手** 客户端收到服务器的SYN-ACK响应后,会发送一个ACK段作为确认。该段中,客户端将确认号设置为服务器的序列号加1(y + 1),并清除SYN标志位。此时,客户端和服务器均进入ESTABLISHED状态,连接正式建立。 例如:`ACK = 1, Acknowledgment Number = 3573692787 + 1` [^2]。 通过这三次握手,客户端和服务器成功交换了初始序列号,并确认了彼此的发送和接收能力。 #### 三次握手的必要性 - **解决网络延迟导致的重复分组问题**:通过三次握手可以确保旧的连接请求在网络中失效,避免因历史连接造成的资源浪费。 - **确认双方的发送/接收能力正常**:三次握手能够验证客户端和服务器都能正常发送和接收数据。 - **协商初始序列号**:每次连接都会使用不同的初始序列号,以防止数据混淆。 - **避免死锁问题**:如果只使用两次握手,可能会导致服务器认为连接已经建立,而客户端尚未确认,从而形成类似死锁的问题 [^4]。 #### 三次握手的示例代码(伪代码) 以下是一个简单的TCP连接建立的伪代码示例,展示了客户端和服务器之间的握手过程: ```python # 客户端发送SYN send_SYN_to_server(): syn_packet = create_tcp_packet(syn=1, seq=x) send_packet(syn_packet) # 服务器响应SYN-ACK respond_SYN_ACK(): syn_ack_packet = create_tcp_packet(syn=1, ack=1, seq=y, ack_num=x+1) send_packet(syn_ack_packet) # 客户端发送ACK send_ACK_to_server(): ack_packet = create_tcp_packet(ack=1, ack_num=y+1) send_packet(ack_packet) ``` #### 三次握手的总结 三次握手的本质是通过序列号同步和能力协商建立可靠的逻辑连接。它不仅确保了数据传输的可靠性,还有效避免了网络延迟和重复连接请求带来的问题。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值