TCP协议通讯工作原理

本文详细介绍了TCP协议的工作原理,包括三次握手过程、TCP标志的作用、端口的概念、TCP缓存机制及TCP进站处理流程等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、TCP三次握手
  传输控制协议(Transport Control Protocol)是一种面向连接的,可靠的传输层协议。面向连接是指一次正常的TCP传输需要通过在TCP客户端和TCP服务端建立特定的虚电路连接来完成,该过程通常被称为“三次握手”。可靠性可以通过很多种方法来提供保证,在这里我们关心的是数据序列和确认。TCP通过数据分段(Segment)中的序列号保证所有传输的数据可以在远端按照正常的次序进行重组,而且通过确认保证数据传输的完整性。要通过TCP传输数据,必须在两端主机之间建立连接。举例说明,TCP客户端需要和TCP服务端建立连接,过程如下所示:

TCP Client

Flags

TCP Server

1 Send SYN (seq=w)

----SYN--->

SYN Received

2 SYN/ACK Received

<---SYN/ACK----

Send SYN (seq=x), ACK (w+1)

3 Send ACK (x+1)

----ACK--->

ACK Received, Connection Established

w: ISN (Initial Sequence Number) of the Client

x: ISN of the Server

在第一步中,客户端向服务端提出连接请求。这时TCP SYN标志置位。客户端告诉服务端序列号区域合法,需要检查。客户端在TCP报头的序列号区中插入自己的ISN。服务端收到该TCP分段后,在第二步以自己的ISN回应(SYN标志置位),同时确认收到客户端的第一个TCP分段(ACK标志置位)。在第三步中,客户端确认收到服务端的ISN(ACK标志置位)。到此为止建立完整的TCP连接,开始全双工模式的数据传输过程。

二、TCP标志

这里有必要介绍一下TCP分段中的标志(Flag)置位情况。如下图所示:

    *SYN:同步标志
  同步序列编号(Synchronize Sequence Numbers)栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。

  *ACK:确认标志
  确认编号(Acknowledgement Number)栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1,Figure-1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。

  *RST:复位标志
  复位标志有效。用于复位相应的TCP连接。

  *URG:紧急标志
  紧急(The urgent pointer) 标志有效。紧急标志置位,

  *PSH:推标志
  该标志置位时,接收端不将该数据进行队列处理,而是尽可能快将数据转由应用处理。在处理 telnet 或 rlogin 等交互模式的连接时,该标志总是置位的。

  *FIN:结束标志
  带有该标志置位的数据包用来结束一个TCP回话,但对应端口仍处于开放状态,准备接收后续数据。

三、TCP端口

  为了能够支持同时发生的并行访问请求,TCP提供一种叫做“端口”的用户接口。端口是操作系统核心用来识别不同的网络回话过程。这是一个严格的传输层定义。通过TCP端口和IP地址的配合使用,可以提供到达终端的通讯手段。实际上,在任时刻的互联网络连接可以由4个数字进行描述: 来源IP地址和来源端口,目的IP地址和目的端口。位于不同系统平台,用来提供服务的一端通过标准的端口提供相应服务。举例来说,标准的TELNET守护进程(telnet daemon)通过监听TCP 23端口,准备接收用户端的连接请求。

四、TCP缓存(TCP Backlog)

  通常情况下,操作系统会使用一块限定的内存来处理TCP连接请求。每当用户端发送的SYN标志置位连接请求到服务端的一个合法端口(提供TCP服务的一端监听该端口)时,处理所有连接请求的内存使用量必须进行限定。如果不进行限定,系统会因处理大量的TCP连接请求而耗尽内存,这在某种程度上可以说是一种简单的DoS攻击。这块经过限定的,用于处理TCP连接的内存称为TCP缓存(TCP Backlog),它实际上是用于处理进站(inbound)连接请求的一个队列。该队列保存那些处于半开放(half-open)状态的TCP连接项目,和已建立完整连接但仍未由应用程序通过accept()调用提取的项目。如果这个缓存队列被填满,除非可以及时处理队列中的项目,否则任何其它新的TCP连接请求会被丢弃。

  一般情况下,该缓存队列的容量很小。原因很简单,在正常的情况下TCP可以很好的处理连接请求。如果当缓存队列填满的时候新的客户端连接请求被丢弃,客户端只需要简单的重新发送连接请求,服务端有时间清空缓存队列以相应新的连接请求。

  在现实环境中,不同操作系统支持TCP缓冲队列有所不同。在BSD结构的系统中,如下所示:

OS

Backlog

BL+ Grace

Notes

SunOS 4.x.x

5

8

 

IRIX 5.2

5

8

 

Linux 1.2.x

10

10

Linux does not have this grace margin

FreeBSD 2.1.0

 

32

 

FreeBSD 2.1.5

 

128

 

Win NTs 3.5.1

6

6

NT does not appear to have this margin

Win NTw 4.0

6

6

NT has a pathetic backlog

五、TCP进站(Inbound)处理过程

    为了更好的讲述TCP SYN Flood的攻击过程,我们先来介绍一下正常情况下,TCP进站处理的过程。

  服务端处于监听状态,客户端用于建立连接请求的数据包(IP packet)按照TCP/IP协议堆栈组合成为TCP处理的分段(segment)。

  分析报头信息: TCP层接收到相应的TCP和IP报头,将这些信息存储到内存中。

  检查TCP校验和(checksum):标准的校验和位于分段之中(Figure-2)。如果检验失败,不返回确认,该分段丢弃,并等待客户端进行重传。

  查找协议控制块(PCB{}):TCP查找与该连接相关联的协议控制块。如果没有找到,TCP将该分段丢弃并返回RST。(这就是TCP处理没有端口监听情况下的机制) 如果该协议控制块存在,但状态为关闭,服务端不调用connect()或listen()。该分段丢弃,但不返回RST。客户端会尝试重新建立连接请求。

  建立新的socket:当处于监听状态的socket收到该分段时,会建立个子socket,同时还有socket{},tcpcb{}和pcb{}建立。这时如果有错误发生,会通过标志位来拆除相应的socket和释放内存,TCP连接失败。如果缓存队列处于填满状态,TCP认为有错误发生,所有的后续连接请求会被拒绝。这里可以看出SYN Flood攻击是如何起作用的。

  丢弃:如果该分段中的标志为RST或ACK,或者没有SYN标志,则该分段丢弃。并释放相应的内存。

### Modbus TCP通信协议工作原理 #### 1. 协议基础 Modbus TCP是一种基于以太网的通信协议,它是传统Modbus协议在网络层面上的扩展。通过TCP/IP协议栈的支持,Modbus TCP能够在局域网或广域网上实现高效的数据传输[^2]。 #### 2. 数据帧结构 Modbus TCP的消息封装在标准的TCP数据包中。它的消息帧由以下几个部分组成: - **事务标识符 (Transaction Identifier)**:用于匹配请求和响应消息。 - **协议标识符 (Protocol Identifier)**:通常固定为0,表示这是一个标准的Modbus TCP报文。 - **长度字段 (Length Field)**:指示后续字节的数量。 - **单元标识符 (Unit Identifier)**:指定目标设备地址。 - **PDU (Protocol Data Unit)**:即传统的Modbus应用层数据单元,包含功能码和数据区[^1]。 #### 3. 功能码的作用 Modbus TCP支持多种功能码来定义具体的操作行为。以下是常见的功能码及其用途: - `0x01`:读取线圈状态。 - `0x02`:读取离散输入状态。 - `0x03`:读取保持寄存器。 - `0x04`:读取输入寄存器。 - `0x05`:写单个线圈。 - `0x06`:写单个寄存器。 - `0x0F`:写多个线圈。 - `0x10`:写多个寄存器[^3]。 每种功能码对应特定的应用场景,例如监控传感器状态、控制执行机构动作或者批量更新参数设置。 #### 4. 客户端与服务器交互流程 在一个典型的Modbus TCP通信环境中,存在客户端(Master)和服务端(Slave)。它们之间遵循以下基本交互逻辑: - 客户端发送带有明确指令的功能码至服务端。 - 服务端接收并解析该命令后返回相应的结果集给客户端。 整个过程依赖于可靠的连接机制以及精确的时间同步管理策略。 ```python import socket def modbus_tcp_request(host, port=502): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port)) # 构造简单的MODBUS 请求头 + PDU 示例 transaction_id = b'\x00\x01' # Transaction ID protocol_id = b'\x00\x00' # Protocol ID always zero for MODBUS/TCP length_field = b'\x00\x06' # Length of the following fields in bytes unit_id = b'\x01' # Slave/Unit Address function_code = b'\x03' # Example Function Code: Read Holding Registers start_addr = b'\x00\x00' # Starting address to read from quantity = b'\x00\x0A' # Number of registers to read request_frame = transaction_id + protocol_id + length_field + unit_id + \ function_code + start_addr + quantity sock.send(request_frame) response_data = sock.recv(1024) print("Response:", response_data.hex()) except Exception as e: print(f"Error occurred during communication: {e}") finally: sock.close() modbus_tcp_request('192.168.1.1') ``` 上述代码片段展示了如何利用Python构建一个简易版的Modbus TCP查询工具,向远程主机发起读取操作,并打印接收到的结果。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值