一、面向连接的特性
在计算机网络通信中,面向连接的传输方式是一种在数据传输前先建立稳定连接的机制。对于TCP(传输控制协议)而言,这种连接的建立是确保数据可靠传输的关键步骤。在建立连接时,需要确定通信双方的唯一标识,即源IP地址、目标IP地址、源端口和目标端口,这四个元素组合成所谓的“TCP的四元组”。通过这四个信息,可以精准地区分和标识出一条特定的TCP连接,保证数据能够准确无误地在正确的通信端点之间进行传输。
二、TCP报文结构
TCP报文结构是TCP协议的核心组成部分,它包含了丰富的控制信息和数据传输机制,以确保数据在网络中的可靠传输。下面将对TCP报文结构的各个字段进行详细解析。
(一)源端口和目的端口
源端口和目的端口分别占2个字节,用于标识通信双方的端口号。源端口是发送方应用程序的端口号,目的端口是接收方应用程序的端口号。通过这两个端口号,可以确保数据被正确地发送到目标应用程序,实现不同应用程序之间的通信。
(二)序列号
序列号占4个字节,用于对TCP传输的数据进行编号。由于TCP是基于“字节流”的协议,每个传输的字节都有一个对应的序列号。序列号的存在使得接收方能够对收到的数据进行重组和排序,确保数据的完整性和顺序性。在连接建立过程中,初始序列号通过三次握手确定,后续数据传输中,每个字节的数据都有唯一的序列号,以便接收方进行确认和重组。
(三)确认号
确认号占4个字节,是接收方期望收到发送方发送的下一个字节的序号。它体现了TCP的累积确认机制,通过这一机制,接收方可以对已正确接收的数据进行确认,同时通知发送方哪些数据还需要重传,从而提高数据传输的可靠性。例如,如果接收方收到序列号为1到1000的字节数据,它会发送确认号为1001的确认报文段,表示已经正确接收了前1000个字节,期望接收下一个字节序号为1001的数据。
(四)首部长度
首部长度占4位,用于表示TCP报文头部的长度,以4字节为单位。由于TCP报文存在选项字段,其头部长度是可变的,最短为20字节。首部长度字段的存在使得接收方能够准确解析出报文头部的结束位置,进而正确处理报文中的数据部分。例如,如果首部长度为5,则表示TCP报文头部长度为5×4=20字节。
(五)保留字段
保留字段占6位,目前未被使用,保留为今后的发展做准备。这些位的值应为0。
(六)标志位
标志位共有6位,从左到右依次为紧急指针(URG)、确认(ACK)、推送(PSH)、复位(RST)、同步(SYN)和终止(FIN)。这些标志位用于控制TCP连接的建立、数据传输和连接终止等过程。
-
紧急指针(URG):当URG=1时,表示本报文段中有紧急数据,紧急指针字段有效。紧急指针指出本报文段中紧急数据的结束位置,用于实现带外数据传输。
-
确认(ACK):当ACK=1时,确认号字段有效。TCP规定,在连接建立后,所有作为确认的报文段都必须把ACK置为1。
-
推送(PSH):当PSH=1时,表示接收方应该尽快将本报文段中的数据交给上层应用程序,而不是等待缓冲区填满后再交付。
-
复位(RST):当RST=1时,用于复位一个连接。例如,当收到一个RST报文段时,表示该连接出现严重错误,需要重新建立连接。
-
同步(SYN):当SYN=1时,用于建立连接。在三次握手过程中,客户端发送的第一次握手报文段和服务器发送的第二次握手报文段都带有SYN标志位。
-
终止(FIN):当FIN=1时,用于释放连接。表示发送方已经没有数据发送,希望终止连接。
(七)窗口大小
窗口大小占2个字节,用于流量控制,指出接收方当前能够接收的数据量。窗口大小的值告诉发送方,在不需要接收方再发送确认的情况下,发送方可以发送多少字节的数据。例如,如果窗口大小为5000字节,发送方可以连续发送5000字节的数据,而不需要等待接收方的确认。当窗口大小为0时,表示接收方的接收缓存已满,发送方应停止发送数据,直到接收方发送一个非零窗口大小的确认报文段。
(八)校验和
校验和占2个字节,用于确保TCP报文段在传输过程中的完整性。校验和的计算包括TCP报文段的头部和数据部分,以及一个伪首部。伪首部包括源IP地址、目的IP地址、保留字节、协议号(对于TCP为6)和TCP报文段的长度。接收方在收到报文段后,会重新计算校验和,并与报文段中的校验和进行比较,如果不一致,则丢弃该报文段。
(九)紧急指针
紧急指针占2个字节,仅在URG=1时有效。紧急指针指出本报文段中紧急数据的结束位置,即紧急数据的字节数加1。例如,如果紧急指针的值为100,则表示本报文段中有99字节的紧急数据,从序列号为紧急指针所指的位置开始。
(十)选项字段
选项字段的长度可变,最长可达40字节。常见的选项包括最大报文段长度(MSS)、窗口扩大因子、时间戳等。
-
最大报文段长度(MSS):用于协商双方在数据传输中使用的最大报文段长度。MSS值是指一个报文段中数据部分的最大长度,不包括TCP头部。通过协商MSS值,可以避免报文段在传输过程中因过大而被分片,提高传输效率。
-
窗口扩大因子:用于扩大窗口大小的范围,以适应高速网络环境下的大流量传输。
-
时间戳:用于测量往返时间,提高TCP的性能和可靠性。时间戳选项包括时间戳值和回显时间戳值,用于计算报文段在网络中的延迟。
三、TCP连接建立过程
(一)三次握手
TCP连接的建立通过三次握手过程实现,这一过程是TCP协议可靠性的基础。
-
第一次握手:客户端向服务器发送一个带有SYN(同步序列号)标志位的TCP报文段,请求建立连接。此时,客户端进入SYN_SENT状态,等待服务器的响应。
-
第二次握手:服务器收到客户端的SYN报文段后,会发送一个带有SYN和ACK(确认)标志位的报文段作为回应。这个报文段不仅确认收到了客户端的连接请求,还携带了服务器端的SYN信息,用于客户端对服务器的连接确认。服务器在发送这个报文段后进入SYN_RCVD状态。
-
第三次握手:客户端收到服务器的SYN_ACK报文段后,会发送一个带有ACK标志位的报文段进行确认,这个ACK报文段可以携带数据。服务器收到这个ACK报文段后,连接正式建立,双方进入ESTABLISHED状态,可以开始正式的数据传输。
(二)状态变化
在TCP连接建立过程中,客户端和服务器会经历不同的状态变化。
客户端状态变化:
-
关闭状态(CLOSED):在发送SYN请求建立连接之前,客户端处于关闭状态。
-
SYN_SENT状态:发送SYN请求后,客户端进入SYN_SENT状态,等待服务器的SYN_ACK响应。
-
建立完成(ESTABLISHED)状态:收到服务器的SYN_ACK报文并发送ACK报文后,客户端进入建立完成状态,此时连接已经建立,可以进行数据传输。
服务器状态变化:
-
关闭状态(CLOSED):服务器应用程序创建一个监听的套接字之前,服务器处于关闭状态。
-
侦听状态(LISTEN):当服务器应用程序创建一个监听的套接字后,服务器进入侦听状态,等待客户端的连接请求。
-
SYN_RCVD状态:服务器收到客户端的SYN报文段后,为TCP连接分配缓存空间,并发送SYN_ACK报文段,进入SYN_RCVD状态,等待客户端的ACK响应。
-
建立完成(ESTABLISHED)状态:收到客户端的ACK报文段后,服务器进入建立完成状态,连接正式建立,可以开始数据传输。
四、相关问题探讨
(一)SYN泛洪攻击及应对措施
SYN泛洪攻击是一种常见的拒绝服务攻击(DoS攻击)方式。攻击者通过向服务器发送大量的SYN请求,使服务器分配大量的资源来处理这些连接请求,但由于攻击者不进行第三次握手的ACK响应,导致服务器上存在大量的半连接(处于SYN_RCVD状态的连接),这些半连接会占用服务器的资源,最终可能导致服务器资源耗尽,无法正常响应合法用户的连接请求。
应对SYN泛洪攻击的措施主要有两种:
-
防火墙代理:通过在服务器前部署防火墙代理,防火墙可以对进入的SYN请求进行筛选和代理。防火墙在收到客户端的SYN请求后,会代替服务器与客户端进行三次握手。如果握手成功,防火墙才将请求转发给服务器;如果握手失败,防火墙会直接丢弃该请求,从而减轻服务器的负担,防止服务器资源被恶意消耗。
-
SYN Cookie技术:服务器在收到客户端的SYN请求后,不立即为连接分配缓存空间,而是根据特定的算法计算出一个SYN Cookie值,并将其作为SYN_ACK报文段的初始序列号发送给客户端。当客户端发送ACK报文段进行确认时,服务器会根据客户端返回的序列号重新计算SYN Cookie值,如果匹配成功,才为连接分配资源。这种方法避免了在收到SYN请求时就分配资源,从而有效抵御SYN泛洪攻击。
(二)为什么必须是三次握手
-
为什么不能是两次握手:如果采用两次握手来建立TCP连接,可能会出现旧的重复连接请求干扰新连接的问题。例如,假设客户端发送了一个建立连接的SYN请求,由于网络延迟等原因,这个请求在两次握手后被服务器接受并建立连接。之后,客户端再次发送新的连接请求,但由于两次握手的机制,服务器可能会错误地将旧的连接请求与新的请求混淆,导致连接建立错误或数据传输混乱。而三次握手通过客户端的最后一次确认,可以确保服务器收到的是客户端当前有效的连接请求,从而避免旧的重复连接对新连接造成干扰。
-
为什么不是四次握手:四次握手虽然在理论上也可以实现连接的建立,但会增加连接建立的时间和资源开销。三次握手已经在保证连接建立可靠性的同时,尽可能减少了不必要的通信次数,提高了连接建立的效率。而且,三次握手已经能够满足防止旧连接干扰、确保双方都做好数据传输准备等需求,没有必要再增加握手次数。