TCP 报文段简介
在介绍三次握手和四次挥手之前,先来简单认识一下 TCP 报文段的结构
TCP报文段也分为首部和数据两部分,首部默认情况下一般是20字节长度,但在一些需求情况下,会使用“可选字段”,这时,首部长度会有所增加,但最长不超过60字节。
TCP 首部包含以下内容,请留意其中的控制位,在三次握手和四次挥手过程中会频繁出现:
端口号 (Source Port and Destination Port):每个 TCP 报文段都包含源端和目的端的端口号,用于寻找发送端和接收端应用进程。这两个值加上 IP 首部中的源端 IP 地址和目的端 IP 地址就可以确定一个唯一的 TCP 连接。
序号 (Sequence Number):这个字段的主要作用是用于将失序的数据重新排列。TCP 会隐式地对字节流中的每个字节进行编号,而 TCP 报文段的序号被设置为其数据部分的第一个字节的编号。序号是 32 bit 的无符号数,取值范围是0到 232 - 1。
确认序号 (Acknowledgment Number):接收方在接受到数据后,会回复确认报文,其中包含确认序号,作用就是告诉发送方自己接收到了哪些数据,下一次数据从哪里开始发,因此,确认序号应当是上次已成功收到数据字节序号加 1。只有 ACK 标志为 1 时确认序号字段才有效。
首部长度 (Header Length):首部中的选项部分的长度是可变的,因此首部的长度也是可变的,所以需要这个字段来明确表示首部的长度,这个字段占 4 bit,4 位的二进制数最大可以表示 15,而首部长度是以 4 个字节为一个单位的,因此首部最大长度是 15 * 4 = 60 字节。
保留字段 (Reserved):占 6 位,未来可能有具体用途,目前默认值为0.
控制位 (Control Bits):在三次握手和四次挥手中会经常看到 SYN、ACK 和 FIN 的身影,一共有 6 个标志位,它们表示的意义如下:
URG (Urgent Bit):值为 1 时,紧急指针生效
ACK (Acknowledgment Bit):值为 1 时,确认序号生效
PSH (Push Bit):接收方应尽快将这个报文段交给应用层
RST (Reset Bit):发送端遇到问题,想要重建连接
SYN (Synchronize Bit):同步序号,用于发起一个连接
FIN (Finish Bit):发送端要求关闭连接
窗口大小 (Window):TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个 16 bit 字段,单位是字节, 因而窗口大小最大为 65535 字节。
检验和 (Checksum):功能类似于数字签名,用于验证数据完整性,也就是确保数据未被修改。检验和覆盖了整个 TCP 报文段,包括 TCP 首部和 TCP 数据,发送端根据特定算法对整个报文段计算出一个检验和,接收端会进行计算并验证。
紧急指针 (Urgent Pointer):当 URG 控制位值为 1 时,此字段生效,紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
选项 (Options):这一部分是可选字段,也就是非必须字段,最常见的可选字段是“最长报文大小 (MSS,Maximum Segment Size)”。
有效数据部分 (Data):这部分也不是必须的,比如在建立和关闭 TCP 连接的阶段,双方交换的报文段就只包含 TCP 首部。
关于 TCP
TCP 提供一种面向连接的、可靠的字节流服务
在一个 TCP 连接中,仅有两方进行彼此通信。广播和多播不能用于 TCP
TCP 使用校验和,确认和重传机制来保证可靠传输
TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制
TCP并不能保证数据一定会被对方接收到,因为这是不可能的。它不是100%可靠的协议,它所能提供的是数据的可靠传递或故障的可靠通知。
三次握手常见问题:
1。说一说三次握手
三次握手是TCP协议用于建立可靠连接的过程,其步骤如下:
第一次握手(SYN):客户端向服务器发送SYN包,请求建立连接。该包中包含一个随机生成的初始序列号ISN(Initial Sequence Number)。
第二次握手(SYN+ACK):服务器收到SYN包后,向客户端发送SYN+ACK包,表示同意建立连接。该包中也包含一个随机生成的序列号ISN,同时将确认序列号ACK设置为客户端的ISN+1。
第三次握手(ACK):客户端收到服务器的SYN+ACK包后,向服务器发送ACK包,表示客户端也同意建立连接。该包的序列号设置为服务器的ISN+1,确认序列号设置为服务器的ISN+1。
在三次握手完成后,TCP连接建立成功,双方可以开始进行数据传输。这个过程可以确保连接的可靠性和完整性,防止数据包的丢失或重复传输。
2.三次握手的作用
三次握手的作用如下:
建立可靠连接:三次握手可以确保客户端和服务器之间建立起可靠的连接,防止数据包的丢失或重复传输。
防止旧连接的混淆:由于网络延迟等原因,可能会出现旧连接的数据包在新连接中被误认为是有效数据包的情况。而三次握手过程中随机生成的ISN可以防止这种情况的发生。
防止恶意连接:三次握手可以防止未经授权的恶意连接,例如SYN洪泛攻击等。如果服务器收到的SYN包并没有相应的ACK包,那么服务器就不会认为这是一条有效的连接请求,从而防止恶意连接。
总之,三次握手是TCP协议用于建立可靠连接的基本过程,其作用在于确保连接的可靠性、完整性和安全性。
3.ISN是固定的吗
ISN(Initial Sequence Number)是随机生成的,通常由操作系统的伪随机数生成器生成。因此,每次建立连接时都会生成一个新的ISN。ISN的目的是防止旧连接的混淆和防止恶意连接,因此它需要是随机的、不可预测的。
ISN的长度通常为32位(4字节),因此ISN的取值范围为0~2^32-1。在TCP连接建立的过程中,ISN会被客户端和服务器分别使用,以确保连接的可靠性和完整性。
需要注意的是,ISN是由操作系统生成的,而不是由应用程序生成的。这意味着在同一台计算机上运行的不同应用程序,它们建立的连接的ISN是不同的。同时,在不同的计算机上生成的ISN也可能不同,这取决于操作系统实现ISN的方式。
4.什么是半链接序列
"半连接序列"是指在TCP三次握手过程中,当服务器收到客户端的SYN包后,它会发送一个SYN+ACK包作为响应,此时连接处于半开状态,即服务器已经准备好接收客户端的数据,但客户端还没有发送ACK包确认连接的建立。
在这种情况下,服务器会在等待一段时间(通常称为“半连接超时时间”),等待客户端发送ACK包,如果在规定的时间内没有收到客户端的ACK包,服务器会认为客户端没有接收到SYN+ACK包,进而关闭连接并释放资源。这个过程被称为半连接队列(Half-open queue),其中等待ACK包的连接称为半连接(Half-open connection)。
半连接队列是用于存储等待客户端ACK的连接队列。在Linux操作系统中,可以使用netstat命令查看半连接队列的大小。当半连接队列的大小超过一定阈值时,服务器可能会拒绝新的连接请求,以避免资源耗尽。因此,在设计应用程序时需要注意合理设置半连接队列的大小,以确保系统的稳定性和可靠性。
5.三次握手过程中可以携带数据吗
在TCP三次握手的过程中,不会携带应用层数据。三次握手的过程是在TCP协议层次进行的,而应用层的数据传输是在TCP连接建立之后进行的。
三次握手的过程中,客户端和服务器之间仅仅交换了一些控制信息,例如序列号、确认号等,用于建立可靠的连接和确认连接的建立。在第三次握手之后,双方的TCP协议都已经确认了连接的建立,可以进行数据传输。
一旦TCP连接建立完成,应用程序就可以使用该连接进行数据的传输。在传输数据时,数据会被封装在TCP的数据段中,然后通过TCP连接进行传输。因此,在TCP连接建立完成之前,应用程序不能进行数据的传输。
6.三次握手的安全性怎么样
TCP三次握手是一种可靠的连接建立方式,也是一种安全的连接建立方式。它可以确保连接建立时,双方的TCP协议栈都已经认可了对方的身份,从而避免了连接被第三方篡改或冒充的风险。
在TCP三次握手的过程中,第三次握手中的ACK包中确认号(ACK number)是根据第二次握手中的序列号(Sequence number)加1生成的,这样可以确保双方都能够正确地识别对方的身份和数据传输的正确性。同时,TCP还使用随机的ISN(Initial Sequence Number)来防止重放攻击,这使得攻击者很难猜测序列号,从而防止攻击者模拟另一方进行连接。
虽然三次握手是一种安全可靠的连接建立方式,但在实际应用中,仍然存在一些安全威胁。例如,攻击者可能通过伪造IP地址或端口号等方式进行欺骗或攻击。因此,在实际应用中,还需要使用一些其他的安全机制来保护TCP连接的安全,例如TLS(Transport Layer Security)协议等。
7.三次握手最大的问题是什么
TCP三次握手的最大问题是SYN洪泛攻击(SYN flood attack)。SYN洪泛攻击是一种常见的网络攻击,攻击者向服务器发送大量的SYN包,但并不发送ACK包来完成连接建立,从而导致服务器的半连接队列满,无法接受新的连接请求,最终导致服务不可用或崩溃。
SYN洪泛攻击利用了TCP三次握手的过程中,服务器需要为每一个收到的SYN包创建一个半连接的特点。当攻击者发送大量的SYN包时,服务器需要为每一个SYN包都创建一个半连接,而由于攻击者不发送ACK包,这些半连接会一直保持,直到超时才会被清除,从而消耗服务器的资源,导致服务器无法正常处理新的连接请求。
为了防止SYN洪泛攻击,可以使用一些防御措施,例如在网络边界处使用防火墙、使用SYN cookie技术、调整半连接队列的大小、限制同一IP地址的连接数量等等。这些措施可以有效地缓解SYN洪泛攻击对服务器的影响。
8.你觉得三次握手还有哪些需要注意的问题
除了SYN洪泛攻击这个已经提到过的问题,TCP三次握手还有一些需要注意的问题,如下:
超时重传:在三次握手的过程中,如果一方没有收到对方发送的数据包,则需要重传该数据包,直到成功建立连接或达到最大重传次数。超时重传的时间应该根据实际情况进行调整,以确保在网络环境不稳定或延迟较高的情况下仍能够成功建立连接。
中间人攻击:TCP三次握手中的数据包可以被攻击者劫持,从而实施中间人攻击。为了防止中间人攻击,可以使用TLS协议等加密通信机制来确保通信的安全性。
处理半连接队列:在TCP三次握手的过程中,服务器需要维护一个半连接队列来处理未完成的连接请求。如果半连接队列满了,则无法处理新的连接请求,从而导致服务不可用。因此,在实际应用中,需要根据实际情况来调整半连接队列的大小,以避免出现此类问题。
不同操作系统实现的差异:不同操作系统在实现TCP协议栈时可能存在一些细微的差异,例如超时时间的设置、ISN的生成方式等。在开发应用程序时,需要考虑这些差异,以确保程序在不同操作系统上都能够正常工作。
综上所述,TCP三次握手是一种可靠的连接建立方式,但在实际应用中,还需要注意一些细节问题,以确保连接的安全和稳定。
9.TCP 建立连接为什么要三次握手而不是两次?
网上大多数资料对这个问题的回答只有简单的一句:防止已过期的连接请求报文突然又传送到服务器,因而产生错误,这既不够全面也不够具体。下面给出比较详细而全面的回答:
防止已过期的连接请求报文突然又传送到服务器,因而产生错误 在双方两次握手即可建立连接的情况下,假设客户端发送 A 报文段请求建立连接,由于网络原因造成 A 暂时无法到达服务器,服务器接收不到请求报文段就不会返回确认报文段,客户端在长时间得不到应答的情况下重新发送请求报文段 B,这次 B 顺利到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,客户端在收到 确认报文后也进入 ESTABLISHED 状态,双方建立连接并传输数据,之后正常断开连接。此时姗姗来迟的 A 报文段才到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,但是已经进入 CLOSED 状态的客户端无法再接受确认报文段,更无法进入 ESTABLISHED 状态,这将导致服务器长时间单方面等待,造成资源浪费。
三次握手才能让双方均确认自己和对方的发送和接收能力都正常
第一次握手:客户端只是发送处请求报文段,什么都无法确认,而服务器可以确认自己的接收能力和对方的发送能力正常;
第二次握手:客户端可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常
第三次握手:服务器可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常;
可见三次握手才能让双方都确认自己和对方的发送和接收能力全部正常,这样就可以愉快地进行通信了。
告知对方自己的初始序号值,并确认收到对方的初始序号值
TCP 实现了可靠的数据传输,原因之一就是 TCP 报文段中维护了序号字段和确认序号字段,也就是图中的 seq 和 ack,通过这两个字段双方都可以知道在自己发出的数据中,哪些是已经被对方确认接收的。这两个字段的值会在初始序号值得基础递增,如果是两次握手,只有发起方的初始序号可以得到确认,而另一方的初始序号则得不到确认。
10.网络是不可靠的,那建立连接不是会经过三次握手吗?那要是在中途丢了,怎么办?
假设第一个包丢了,客户端发送给服务端的 SYN 包丢了(简而要之就是服务端没接收到客户端的SYN包)。客户端迟迟收不到服务端的ACK包,那会周期性超时重传,直到收到服务端的ACK。假设第二个包丢了,服务端发送的SYN+ACK包丢了(简而要之就是客户端没接收到服务端的SYN+ACK包)。服务端迟迟收不到客户端的ACK包,那会周期性超时重传,直到收到客户端的ACK。假设第三个包丢了(ACK包),客户端发送完第三个包后单方面进入了 ESTABLISHED 状态,而服务端也认为此时连接是正常的,但第三个包没到达服务端。
一、如果此时客户端与服务端都还没数据发送,那服务端会认为自己发送的SYN+ACK的包没发送至客户端,所以会超时重传自己的SYN+ACK包。
二、如果这时候客户端已经要发送数据了,服务端接收到了ACK + Data数据包,那自然就切换到 ESTABLISHED 状态下,并且接收客户端的Data数据包。
三、如果此时服务端要发送数据了,但发送不了,会一直周期性超时重传SYN + ACK,直到接收到客户端的ACK包。