网络运输层之(1)TCP连接管理
网络运输层之(1)TCP连接管理
Author: Once Day Date: 2024年10月22日
一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦…
漫漫长路,有人对你微笑过嘛…
全系列文章可参考专栏: 通信网络技术_Once-Day的博客-CSDN博客。
参考文章:
- 《TCP/IP详解卷一》
- TCP协议详解 (史上最全)-CSDN博客
- TCP协议详解 - 知乎 (zhihu.com)
- 计算机网络:这是一份非常全面&详细的TCP/IP协议学习指南-腾讯云开发者社区-腾讯云 (tencent.com)
- 计算机网络原理梳理丨清晰认识 TCP/IP 协议-腾讯云开发者社区-腾讯云 (tencent.com)
文章目录
- 网络运输层之(1)TCP连接管理
- 1. TCP连接管理
- 1.1 连接的建立与终止
- 1.2 半关闭
- 1.3 同时打开和关闭
- 1.4 初始化序列号
- 1.5 连接超时
- 2. TCP选项
- 2.1 最大段大小选项
- 2.2 选择确认选项
- 2.3 窗口缩放选项
- 2.4 时间戳选项和防回绕序列号
- 2.5 用户超时选项
- 2.6 认证选项
- 3. TCP特性
- 3.1 TCP路径最大传输单元发现(MSS)
- 3.2 TCP状态转换
- 3.3 重置报文段
- 3.4 与TCP连接相关的攻击
1. TCP连接管理
1.1 连接的建立与终止
TCP提供面向连接的可靠数据传输服务。它在传输层协议中占据核心地位。
(1) 建立连接(三次握手)
- 客户端发送
SYN
同步报文,随机生成一个初始序列号seq=x
,标志位SYN=1
,发送到服务器。 - 服务器接收到
SYN
报文后,回复SYN+ACK
报文,确认号ack=x+1
,同时也生成一个随机序列号seq=y
,标志位SYN=1
,ACK=1
。 - 客户端收到服务器的
SYN+ACK
后,回复ACK
确认报文,确认号ack=y+1
,序列号seq=x+1
,标志位ACK=1
。 - 双方都收到对方的ACK确认后,TCP连接就建立成功了。连接建立后,会形成一个唯一的会话四元组,即(源IP,源端口,目的IP,目的端口),通过四元组能够唯一标识一个TCP连接。
三次握手能够可靠地建立一个双向的TCP连接,客户端和服务器都能够确认自己和对方的发送与接收能力正常。避免了连接时的歧义和资源浪费。
(2) 数据传输
- TCP连接建立后,双方按照三次握手确定的初始序列号,开始传输数据。
- 发送方给每个传输的字节分配一个序列号
seq
。接收方收到数据后,发送ACK
确认报文,确认号ack=seq+len
。 - 发送方收到接收方的
ACK
后,就确认数据传输成功,然后滑动发送窗口,用新的序列号继续发送后续数据。 - TCP利用序列号、确认应答、重传、流量控制、拥塞控制等机制,能够实现可靠的数据传输。
TCP的字节流服务、全双工通信以及滑动窗口协议,使得应用层看到的似乎是一个无差错、不会丢失、不会重复、保序的数据流。实际的网络物理链路却可能出现丢包、重复、错序等各种问题。TCP正是提供了复杂的机制来解决这些问题,从而呈现简单可靠的服务。
(3) 连接终止(四次挥手)
- 主动关闭方发送
FIN
结束报文,seq=m
,标志位FIN=1
,表示数据发送完毕,请求关闭连接。 - 被动关闭方收到
FIN
后,回复ACK
确认,ack=m+1
。此时主动方到被动方的单向连接就释放了。TCP连接进入半关闭状态。被动方仍可以继续发送数据。 - 被动方数据发送完毕后,也发送
FIN
结束报文,seq=n
,标志位FIN=1
。 - 主动方收到
FIN
后,回复ACK
确认,ack=n+1
。 - 主动方等待
2MSL
(最大报文段生存时间)后,没有再收到被动方的数据,就完全关闭TCP连接。被动方收到ACK后,就直接关闭连接。
四次挥手能够可靠地终止一个TCP连接。相比三次握手,多出的一次挥手是为了处理半关闭状态。这样每个方向上都能独立关闭连接,不会丢失数据。2MSL等待状态则是为了让迟到的数据包都消失,新连接不会混淆。
1.2 半关闭
TCP半关闭(TCP half-close)是指在一个TCP连接中,通信的一方关闭了数据的发送,但仍保持接收数据的能力。这种状态下的TCP连接称为半关闭连接。半关闭为TCP连接提供了更灵活的控制方式,特别适用于客户端和服务器需要相互独立地关闭发送通道的场景。
(1) 半关闭的原理
- 全双工的TCP连接可以看作两个单工的信道:客户端到服务器、服务器到客户端。
- 当通信的一方发送
FIN
报文关闭其单工信道时,另一方的单工信道仍能继续发送数据。此时TCP连接进入半关闭状态。 - 直到另一方也发送
FIN
关闭其单工信道,整个TCP连接才完全关闭。
(2) 半关闭的状态
- 客户端关闭发送通道后,状态变为
FIN_WAIT_1
,收到服务器ACK
后变为FIN_WAIT_2
。 - 此时服务器状态变为
CLOSE_WAIT
,表示客户端已经关闭了其发送通道,但服务器仍可以继续发送数据。 - 服务器完成其所有数据发送后,也发送
FIN
,状态变为LAST_ACK
。 - 客户端收到服务器的
FIN
后,回复ACK
,然后经过TIME_WAIT
,最终完全关闭。
可见,半关闭引入了FIN_WAIT_2
和CLOSE_WAIT
两个特殊的状态,使得连接双方能够有序地独立关闭各自的发送通道。避免了发送FIN
的一方过早关闭连接,导致另一方的数据丢失。
(3) 编程接口中的半关闭
在伯克利套接字编程接口中,可以使用shutdown
函数实现半关闭。int shutdown(int sockfd, int how)
可以控制关闭TCP连接的某个单向数据流。其中how
参数有三种取值:SHUT_RD
关闭读通道、SHUT_WR
关闭写通道、SHUT_RDWR
同时关闭读写通道。
例如,在服务器端调用shutdown(sockfd, SHUT_WR)
后,sockfd
就只能接收数据,不能发送数据。服务器再调用read(sockfd)
读取客户端发来的数据,直到读取到EOF
。与close
函数直接关闭整个连接不同,shutdown
能关闭部分数据流,提供了半关闭的能力。
下面是一个简单的服务器端半关闭示例:
// 服务器关闭写通道,只保留读通道
shutdown(sockfd, SHUT_WR);
// 继续从sockfd读取客户端数据,直到EOF
while((n = read(sockfd, buf, BUFSIZE)) > 0) {// 处理读取到的数据
}
// 关闭整个连接
close(sockfd);
1.3 同时打开和关闭
TCP同时打开(TCP Simultaneous Open)和同时关闭(TCP Simultaneous Close)是TCP连接建立和终止过程中的两种特殊情况。它们分别对应于连接双方同时发起建立请求和关闭请求的场景。
TCP同时打开:
- 同时打开发生于连接双方几乎同时发送
SYN
报文的情况。 - 客户端和服务器都主动打开连接,各自发送
SYN
报文,并进入SYN_SENT
状态。 - 双方收到对方的
SYN
后,就将其视为SYN+ACK
,同时转换到ESTABLISHED
状态。 - 双方再各自回复一个
ACK
,确认收到对方的SYN
。 - 至此,TCP连接建立完成。整个过程实际上只有二次握手,但是有四个报文。
与三次握手的区别:
- 角色对等:同时打开的双方都是主动发起方,而不分客户端和服务器。
- 状态变化:同时打开少了一个
SYN_RCVD
状态,双方直接从SYN_SENT
到ESTABLISHED
。 - 握手次数:同时打开只有两次握手,比三次握手少一次。
TCP同时关闭:
- 同时关闭发生于连接双方几乎同时发送
FIN
报文的情况。 - 此时双方的状态都从
ESTABLISHED
直接转换到CLOSING
。 - 双方都收到对方的
FIN
后,就将其视为FIN+ACK
,同时转换到TIME_WAIT
状态。 - 等待
2MSL
时间后,如果没有收到对方的数据,就关闭连接,转换到CLOSED
状态。 - 整个过程只有二次挥手,没有出现半关闭状态。
与四次挥手的区别:
- 状态变化:同时关闭没有半关闭状态如
CLOSE_WAIT
和LAST_ACK
, 而是新增一个CLOSING
状态。 - 挥手次数:同时关闭只有两次挥手,比四次挥手少两次。
- 连接终止:同时关闭的双方都要经过
TIME_WAIT
,而四次挥手只有主动方有TIME_WAIT
。
需要注意的是,虽然同时打开和关闭能够简化建立和终止过程,但它们出现的概率较低。大多数情况下,TCP连接还是由明确的客户端和服务器通过三次握手、四次挥手来建立和终止。三次握手和四次挥手更具典型性,同时打开和关闭反而是一种例外情况。
下面是同时打开和同时关闭的状态变化示意:
同时打开:
CLOSED -> SYN_SENT -> ESTABLISHED同时关闭:
ESTABLISHED -> CLOSING -> TIME_WAIT -> CLOSED
1.4 初始化序列号
TCP初始序列号(Initial Sequence Number, ISN)是TCP连接建立过程中非常重要的一个参数。它决定了后续数据传输的起始序列号,对于保证可靠传输至关重要。如果ISN选择不当,就可能引发连接劫持、数据注入等安全问题。因此,现代操作系统在选择ISN时都采用了一些随机化算法,以增强TCP连接的安全性和鲁棒性。
初始序列号的作用:
- 标识TCP连接:ISN是每个TCP连接的起始序列号,与IP地址和端口号一起唯一标识一个TCP连接。
- 防止历史分节:随机化的ISN能避免新连接误用上一个相同四元组连接的历史分节。
- 防止伪造分节:ISN的不可预测性增加了攻击者伪造合法分节的难度。
初始序列号的生成算法:
- 时钟算法:最简单的算法是用一个计时器从0开始计数,每4微秒加1。这个算法容易被猜测,安全性较差。
- 基于时钟的随机增量算法:在时钟算法的基础上,每次加一个随机增量(如64000到128000之间)。安全性有所提高,但仍可能被统计分析。
- RFC1948算法:
ISN = M + F(localhost, localport, remotehost, remoteport)
。其中M是一个计时器,每4微秒加1;F是一个Hash算法,根据连接四元组生成一个随机值。这个算法在Linux、FreeBSD等系统中广泛使用。 - 加密算法:使用安全的加密算法如MD5、SHA-1等,根据时钟、四元组、密钥等因素生成ISN。这种算法安全性最高,但计算开销也最大。
常见系统的实现:
-
Linux内核使用了一个基于RFC1948的随机化算法,称为
secure_tcp_sequence_number
。它用一个密钥(随机生成,定期更换)、时钟、四元组等作为输入,用MD5算法生成一个32位的哈希值。再用这个哈希值异或一个时间相关的随机值,得到最终的ISN。 -
Windows的
TCP/IP
实现使用了一种称为"加密增强的伪随机数生成器"的算法。该算法使用了类似密钥的种子值、时钟计数器、四元组等作为输入,生成随机的ISN。对于每个连接,会刷新种子值,以进一步增强不可预测性。 -
FreeBSD的实现与Linux类似,也是基于RFC1948的一个变种。主要区别在于使用SHA-1算法代替了MD5,生成160位的哈希值。然后取其高32位与时钟计数器异或,得到最终的ISN。
下面是Linux内核中生成ISN的简化示意:
// 安全的TCP初始序列号生成
static u32 secure_tcp_sequence_number(u32 saddr, u32 daddr, u16 sport, u16 dport) {u32 hash[4];u32 sec, usec;// 获取时钟值get_clock(&sec, &usec); // 用MD5计算四元组的哈希值md5_transform(hash, sec, saddr, sport, daddr, dport, secret_key); // 高32位与时钟异或return seq = hash[0] ^ (saddr + daddr + sec + usec);
}
可见,通过加密算法、时钟、四元组等因素的综合运用,现代操作系统能够生成足够随机和安全的TCP初始序列号。这种随机化虽然会带来一定的计算开销,但相比其在安全性和可靠性方面的提升,这种代价是值得的。
1.5 连接超时
TCP连接超时是指在建立连接、传输数据、关闭连接等各个阶段,由于网络问题、对端崩溃等原因,导致一方迟迟等不到另一方的响应,最终触发超时机制的情况。针对不同的超时场景,TCP协议定义了不同的错误报文和状态,以通知应用程序采取相应的措施。
(1) 连接建立超时:
- 客户端发送
SYN
后,等待服务器的SYN+ACK
超时,称为SYN
超时。 - 客户端通常会重发
SYN
,如果重试次数达到上限还没有收到响应,就放弃连接。 - 这种情况下,客户端会收到
ETIMEDOUT
错误,状态保持在CLOSED
。
(2) 数据传输超时:
- 发送方发送数据后,等待接收方的ACK超时,称为
RTO(Retransmission Timeout)
超时。 - 发送方会重发数据,如果重试次数达到上限还没有收到
ACK
,就认为连接失效。 - 这种情况下,发送方会收到
ETIMEDOUT
错误,连接状态变为CLOSED
。 - 接收方会收到一个
RST
报文,将连接状态也变为CLOSED
。
(3) 连接关闭超时:
- 主动关闭方发送
FIN
后,等待被动关闭方的ACK
超时,称为FIN_WAIT_1
超时。 - 主动关闭方会重发
FIN
,如果重试次数达到上限还没有收到ACK
,就直接关闭连接。 - 这种情况下,主动关闭方会收到
ETIMEDOUT
错误,状态从FIN_WAIT_1
直接变为CLOSED
。 - 被动关闭方会收到一个
RST
报文,将连接状态从CLOSE_WAIT
变为CLOSED
。
(4) 长时间非活动超时:
- 如果一个已建立的连接长时间没有数据传输,称为非活动超时。
- 这种超时通常由操作系统的TCP保活机制触发,默认时间为2小时。
- 保活机制会发送探测报文,如果多次探测都没有响应,就认为连接失效。
- 这种情况下,双方都会收到ETIMEDOUT错误,连接状态变为CLOSED。
(5) TCP重置报文:
- 当一方发送的数据包对于另一方无法接受时,另一方会发送一个RST报文。
- RST报文表示强制重置连接,双方的状态都将直接变为CLOSED。
- 常见的触发RST的情况有:请求建立一个已存在的连接、请求一个不存在的端口、请求一个已关闭的连接等。
- 应用程序收到RST报文后,通常会得到ECONNRESET错误。
下面是一个TCP超时重传的简化示意:
发送方 接收方| || --> 数据seq=1000 ------> || || <-------- 超时 --------> || || --> 数据seq=1000 ------> || || <-------- 超时 --------> || || --> RST --------------> X|| |
2. TCP选项
下面是TCP常见选项的表格:
种类 | 长度 | 名称 | RFC文档 | 描述 |
---|---|---|---|---|
0 | - | End of Option List | RFC 793 | 标志选项列表的结束,用于填充TCP首部的选项字段 |
1 | - | No-Operation | RFC 793 | 用于选项之间的分隔和填充 |
2 | 4 | Maximum Segment Size | RFC 793, 879, 6691 | 指定TCP最大报文段长度(MSS),用于TCP连接建立时协商MSS |
3 | 3 | Window Scale | RFC 7323 | 用于高带宽延迟网络下扩展TCP窗口大小,最大可扩展到30位 |
4 | 2 | SACK Permitted | RFC 2018 | 发起端支持并同意使用SACK选择确认机制 |
5 | N | SACK | RFC 2018, 2883, 6675 | 用于选择确认机制,指明收到的不连续数据块 |
8 | 10 | Timestamp | RFC 7323 | 包含发送和回显时间戳,用于计算RTT和防止序列号回绕 |
14 | 3 | TCP Alternate Checksum Algorithm | RFC 1146 | 指定备用校验和算法,如8位Fletcher算法 |
15 | N | TCP Alternate Checksum Data | RFC 1146 | 与种类(14)配合,携带备用校验和所需数据 |
19 | 18 | MD5 Signature Option | RFC 2385 | 携带MD5签名,用于增强TCP连接的安全性 |
28 | 4 | User Timeout Option | RFC 5482 | 指定用户超时时间,即应用程序等待数据的最长时间 |
29 | N | TCP Authentication Option | RFC 5925 | 提供对TCP段的认证和完整性保护,防止DoS和MITM攻击 |
30 | N | Multipath TCP | RFC 8684 | 实现多路径TCP,允许单个TCP连接利用多个网络路径 |
34 | N | TCP Fast Open | RFC 7413 | 在SYN报文中携带数据,减少连接建立的RTT |
254 | N | Experiment | RFC 4727 | 用于TCP扩展选项的实验和测试 |
2.1 最大段大小选项
TCP的最大段大小(Maximum Segment Size, MSS)选项是TCP性能优化的重要手段之一。它允许通信双方在连接建立阶段协商数据段的最大长度,避免发送过大的数据段导致分片和重组,从而提高TCP传输效率。
MSS选项格式:
- MSS选项的Kind字段值为2,表示这是一个MSS选项。
- MSS选项的Length字段值为4,表示该选项的总长度为4字节。
- MSS选项的Value字段占2字节,表示发送方能够接收的最大TCP数据段长度。
- MSS值不包括TCP首部和选项的长度,只针对TCP数据部分。
0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Kind=2 | Length=4 | MSS Value |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
MSS选项作用:
- 发送方利用MSS告知接收方自己能够接收的最大数据段长度,避免接收到过大的数据段。
- 接收方根据发送方的MSS设置和自身条件,选择一个合适的MSS值,控制发送数据段的大小。
- 合理的MSS值能够减少分片和重组,提高网络利用率和吞吐量。
- MSS值的选择需要综合考虑MTU、TCP首部大小、路径MTU等因素。
MSS选项交互流程:以下是客户端和服务器在TCP连接建立过程中协商MSS的典型交互流程:
- 客户端发送
SYN
报文,在TCP选项中携带自己的MSS值(如1460)。
Client -> Server: SYN, MSS=1460
- 服务器收到
SYN
后,选择一个不大于客户端MSS的值作为自己的MSS
(如1400),并在SYN+ACK
报文中回复该MSS
值。
Server -> Client: SYN+ACK, MSS=1400
-
客户端收到服务器的
MSS
值后,调整自己的发送数据段大小,确保不超过1400字节。 -
服务器收到客户端的
ACK
后,也调整自己的发送数据段大小,确保不超过1460字节。 -
后续的数据传输中,双方就按照协商好的
MSS
值来发送数据段,避免了分片和重组。
下面是一个实际的MSS选项交互示例(在TCP首部中):
// 客户端发送的SYN报文
0x02 0x04 0x05 0xb4// 服务器回复的SYN+ACK报文
0x02 0x04 0x04 0x00
可以看出,客户端的MSS值为1460(0x05b4),服务器选择的MSS值为1024(0x0400),双方最终协商的MSS为1024。这个MSS值在后续的数据传输中会控制TCP数据段的最大长度,避免不必要的分片。
2.2 选择确认选项
TCP的选择确认(Selective Acknowledgment, SACK)是一种重要的丢包恢复机制。它允许接收方告知发送方具体收到了哪些数据段,使发送方能够针对性地重传丢失的数据段,提高了丢包恢复的效率。
(1) SACK选项格式:SACK选项由两个部分组成,SACK-Permitted选项和SACK选项。
- SACK-Permitted选项
(Kind=4, Length=2)
用于在SYN报文中协商是否启用SACK。
0 10 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Kind=4 | Length=2 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- SACK选项
(Kind=5, Length=N)
用于在ACK报文中告知发送方已接收到的不连续数据块。
0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Kind=5 | Length=N | Left Edge 1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Right Edge 1 | Left Edge 2 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Right Edge 2 | ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
其中,Left Edge和Right Edge分别表示已接收数据块的左右边界(序列号),可以包含多个不连续的数据块。
(2) SACK工作原理:
- 发送方在SYN报文中携带
SACK-Permitted
选项,表示自己支持SACK。 - 接收方如果也支持
SACK
,就在SYN+ACK
报文中回复SACK-Permitted
选项。 - 在数据传输过程中,如果接收方收到了不连续的数据段,就在
ACK
报文中使用SACK
选项告知发送方已接收到的数据块。 - 发送方根据
SACK
信息,重传丢失的数据段,直到接收方确认所有数据都已收到。
(3) SACK应用示例
发送方 接收方| || --- 数据段1 (seq=1000) -----> || --- 数据段2 (seq=2000) -----> || --- 数据段3 (seq=3000) --X || --- 数据段4 (seq=4000) -----> || || <--- ACK 3000, SACK=[(4000,5000)] --- || || --- 数据段3 (seq=3000) -----> || || <--- ACK 5000 ---------------- || |
在这个例子中,数据段3丢失,接收方在ACK中使用SACK告知发送方已收到数据段4。发送方重传数据段3后,接收方确认所有数据都已收到。可以看出,SACK机制避免了发送方盲目重传所有未确认数据的问题,提高了丢包恢复效率。
2.3 窗口缩放选项
TCP的窗口缩放(Window Scale)选项是为了解决TCP窗口大小限制而引入的一种机制。它允许通信双方协商一个缩放因子,将窗口大小扩展到原来的65535字节以上,从而提高了高带宽、高延迟网络下的TCP传输性能。
(1) 引入背景:
- TCP首部中的窗口大小字段长度为16位,最大值为65535字节。
- 在高带宽、高延迟网络(如卫星链路)下,65535字节的窗口大小远不够填满带宽时延积(BDP)。
- 窗口过小会导致发送方频繁地等待接收方的确认,降低了传输效率。
- 为了突破65535字节的限制,需要引入一种窗口缩放机制。
(2) 窗口缩放选项格式:窗口缩放选项(Kind=3, Length=3
)用于在SYN
报文中协商缩放因子。
0 1 20 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Kind=3 | Length=3 | Shift Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
其中,Shift Count表示缩放因子,取值范围为0~14。缩放因子用于将窗口大小左移,扩大窗口。
(3) 窗口缩放工作原理:
- 发送方在
SYN
报文中携带窗口缩放选项,指定一个缩放因子(如8)。 - 接收方如果也支持窗口缩放,就在
SYN+ACK
报文中回复窗口缩放选项,也指定一个缩放因子(如7)。 - 此后,双方发送的所有报文中,窗口大小字段的值都要左移相应的缩放因子位。
- 接收方收到报文后,再将窗口大小右移相同的位数,还原真实的窗口大小。
举例来说,如果窗口大小字段为1000,发送方的缩放因子为8,接收方的缩放因子为7,则真实的窗口大小为:
- 发送方发送的窗口大小: 1000 << 8 = 256000字节
- 接收方接收到的窗口大小: 1000 << 7 = 128000字节
可以看出,窗口缩放机制将原本16位的窗口大小扩展到了30位(16+14
),大大突破了65535字节的限制。
(4) 窗口缩放应用示例:
// 客户端发送的SYN报文
0x03 0x03 0x08// 服务器回复的SYN+ACK报文
0x03 0x03 0x07
在这个例子中,客户端和服务器协商的缩放因子分别为8和7。假设后续传输过程中的窗口大小字段为1000,则实际的窗口大小分别为256000字节和128000字节,远大于65535字节的限制。
2.4 时间戳选项和防回绕序列号
TCP的时间戳(Timestamp)选项和防回绕序列号(Protection Against Wrapped Sequence Numbers, PAWS)是为了提高TCP性能和安全性而引入的两种机制。时间戳选项用于精确计算往返时间(RTT)和处理乱序数据段,PAWS机制则用于防止序列号回绕导致的旧数据段被误认为新数据段。
(1) 时间戳选项格式:时间戳选项(Kind=8, Length=10
)由两个32位的时间戳字段组成:
0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Kind=8 | Length=10 | TS Value |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TS Value (continued) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TS Echo Reply |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
其中,TS Value表示数据段发送时的时间戳值,TS Echo Reply
表示上一次收到对方数据段的时间戳值。
(2) 时间戳选项工作原理:
- 发送方在每个数据段中都加入当前的时间戳值。
- 接收方在确认数据段时,将发送方的时间戳值原样复制到
TS Echo Reply
字段。 - 发送方收到确认后,用当前时间减去
TS Echo Reply
,得到一个精确的RTT样本。 - 发送方和接收方还可以根据时间戳值处理乱序数据段,提高传输效率。
(3) 序列号回绕问题:
- TCP使用32位序列号,理论上最大传输4GB数据后序列号就会回绕。
- 如果回绕后的旧数据段延迟到达,接收方可能会误以为是新的数据段,导致数据错乱。
(4) PAWS解决方案:
- 发送方和接收方在时间戳选项中维护一个时间戳时钟(Timestamp Clock)。
- 发送方的时间戳时钟必须是单调递增的,每次发送数据段时都要增加。
- 接收方检查收到数据段的时间戳值,如果小于上一次接收到的时间戳值,就认为是旧的数据段,直接丢弃。
- 由于时间戳值的范围远大于序列号(32位vs16位),因此在序列号回绕期间时间戳值不会回绕,可以有效地区分新旧数据段。
以下是一个简化的时间戳选项和PAWS应用示例:
发送方 接收方| || -- 数据段 (seq=1000, ts=100) --> || || <---- ACK 1000, ts_echo=100 ---- || || -- 数据段 (seq=1000, ts=50) ---> || || (丢弃旧数据段)| |
在这个例子中,发送方在时间戳选项中发送了自己的时间戳值100,接收方在确认数据段时将其复制到ts_echo
字段。后来,发送方重发了一个旧的数据段(可能是因为网络延迟),其时间戳值为50。接收方发现该数据段的时间戳值小于上一次接收到的时间戳值100,因此判断为旧的数据段,直接丢弃。这样就避免了旧数据段被误认为新数据段的问题。
2.5 用户超时选项
TCP的用户超时(User Timeout, UTO)选项是为了让应用程序能够更好地控制TCP连接的超时时间而引入的一种机制。它允许应用程序为每个TCP连接指定一个用户超时时间,当连接空闲时间超过该时间时,TCP将主动关闭连接,避免连接长时间占用系统资源。
(1) 引入背景:
- 传统TCP的超时时间由操作系统内核根据网络条件自适应地调整,应用程序无法直接控制。
- 在某些场景下(如移动网络、电力有限的设备),应用程序希望能够更短的超时时间,以便及时释放连接资源。
- 传统TCP的连接释放机制(如keep-alive)灵活性不够,不能满足应用程序的多样化需求。
(2) UTO选项格式:UTO选项(Kind=28, Length=4
)用于在TCP首部中携带应用程序指定的用户超时时间。
0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Kind=28 | Length=4 |G| User Timeout |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User Timeout (continued) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
其中,G(Granularity)标志位表示用户超时时间的粒度,0表示秒,1表示分钟。User Timeout
字段是一个31位的无符号整数,表示用户超时时间。
(3) UTO工作原理:
- 应用程序在创建TCP连接时,可以通过套接字选项(如TCP_USER_TIMEOUT)设置用户超时时间。
- TCP协议栈将用户超时时间编码到UTO选项中,在SYN报文和后续数据报文中发送给对端。
- 对端TCP协议栈从UTO选项中解码出用户超时时间,作为该连接的空闲超时时间。
- 当连接空闲时间超过用户超时时间时,TCP将发送一个RST报文关闭连接,并通知应用程序。
- 应用程序可以根据需要捕获连接关闭事件,进行相应的处理。
以下是一个简化的UTO应用示例(在TCP首部中):
// 客户端发送的SYN报文
0x1c 0x04 0x00 0x00 0x27 0x10// 服务器回复的SYN+ACK报文
0x1c 0x04 0x00 0x00 0x27 0x10
在这个例子中,客户端和服务器都在SYN报文中携带了UTO选项,G标志位为0,用户超时时间为10000秒(0x2710)。这表示如果连接空闲时间超过10000秒,TCP将自动关闭连接,释放连接资源。
注意事项:
- UTO选项只是一种建议,对端TCP协议栈可以根据自身策略决定是否采纳。
- 为了避免UTO选项被滥用,操作系统内核通常会对用户超时时间的范围进行限制(如1秒到30天)。
- UTO选项的设置需要谨慎,过短的超时时间可能导致连接频繁关闭,过长的超时时间又可能浪费系统资源。
2.6 认证选项
TCP的认证选项(TCP Authentication Option, TCP-AO)是为了增强TCP连接的安全性而引入的一种机制。它允许通信双方在TCP连接建立过程中对数据进行完整性验证和身份认证,防止了TCP会话劫持、重放攻击等安全威胁。
(1) 引入背景:
- 传统TCP缺乏对数据完整性和身份真实性的验证,容易受到会话劫持、中间人攻击等威胁。
- 虽然TCP MD5选项(RFC 2385)提供了一定的完整性保护,但其安全强度不足,且存在密钥管理等问题。
- 为了提供更强的安全保障,IETF开发了TCP-AO(RFC 5925),作为TCP MD5选项的替代者。
(2) TCP-AO格式:TCP-AO选项(Kind=29)的格式如下:
0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Kind=29 | Length | KeyID | Next KeyID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC (Message Authentication Code)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
其中,Length字段表示TCP-AO选项的总长度,KeyID表示当前使用的主密钥(Master Key)标识符,Next KeyID表示下一个要使用的主密钥标识符(用于密钥轮换),MAC字段则是根据数据和密钥计算出的消息认证码。
(3) TCP-AO工作原理:
- 通信双方offline协商一组主密钥和密钥标识符,并设置密钥轮换策略。
- 在TCP连接建立过程中,双方在
SYN
、SYN-ACK
、ACK
报文中携带TCP-AO选项,对数据进行完整性保护。 - 对于每个要发送的TCP报文,发送方根据相应的主密钥和密钥标识符,计算MAC值,并填充到TCP-AO选项中。
- 接收方收到TCP报文后,根据TCP-AO选项中的密钥标识符,查找相应的主密钥,重新计算MAC值,并与报文中的MAC值进行比对。
- 如果MAC值校验通过,说明数据完整性和发送方身份得到了验证,接收方继续处理该TCP报文;否则,认为该报文不可信,直接丢弃。
- 根据密钥轮换策略,通信双方周期性地更换主密钥,保证长期通信的安全性。
以下是一个简化的TCP-AO应用示例(在TCP首部中):
// 客户端发送的SYN报文
0x1d 0x10 0x01 0x02 0x12 0x34 0x56 0x78 0x9a 0xbc 0xde 0xf0 0x11 0x22 0x33 0x44// 服务器回复的SYN-ACK报文
0x1d 0x10 0x01 0x02 0x56 0x78 0x9a 0xbc 0xde 0xf0 0x11 0x22 0x33 0x44 0x55 0x66
在这个例子中,客户端在SYN报文中携带了TCP-AO选项,KeyID为1,Next KeyID为2,MAC值为一个16字节的哈希值。服务器在SYN-ACK报文中也携带了TCP-AO选项,表示接受客户端的认证请求,并附上自己计算的MAC值。后续的数据传输则会继续使用TCP-AO选项进行完整性保护。
注意事项:
- TCP-AO的安全性依赖于离线协商的主密钥,因此主密钥的生成、分发、存储等环节需要有安全保障。
- TCP-AO选项会增加一定的计算开销和数据包长度,对性能有一定影响。
- TCP-AO与其他TCP选项(如时间戳、SACK等)可以同时使用,以获得更好的性能和安全性。
3. TCP特性
3.1 TCP路径最大传输单元发现(MSS)
TCP路径MTU发现(Path MTU Discovery, PMTUD)是一种自适应调整TCP报文段大小的机制,目的是在不产生IP分片的情况下,最大化单个TCP报文段的长度,从而提高TCP传输效率。
(1) PMTUD工作流程:
- 发送方将TCP报文段大小设置为较大的值,如界面MTU或者最大允许的MSS。
- 发送方在IP首部中设置DF(Don’t Fragment)标志,表示不允许中间设备对该数据包进行分片。
- 数据包在网络中传输,如果遇到MTU较小的链路,且数据包长度大于链路MTU,则中间设备丢弃该数据包,并向发送方返回一个ICMP差错报文(“Fragmentation Needed and DF Set”)。
- 发送方收到ICMP差错报文后,从中提取下一跳MTU值,并将TCP报文段大小缩小为该值。
- 发送方继续发送修改后的TCP报文段,重复步骤2-4,直到数据包到达目的地。
- 如果一段时间内没有收到ICMP差错报文,发送方会尝试增大TCP报文段大小,以探测路径MTU是否有所增加(因为路由是动态变化的)。
(2) PMTUD状态分析:PMTUD可以看作是一个有限状态机,主要有以下几种状态:
- Initial状态:发送方使用较大的TCP报文段大小,如界面MTU或最大允许的MSS。
- Searching状态:发送方收到ICMP差错报文后,缩小TCP报文段大小,并继续发送数据,探测路径MTU。
- Found状态:发送方找到了当前路径的MTU值,使用该值作为TCP报文段大小。
- Robustness状态:发送方定期尝试增大TCP报文段大小,以适应路径MTU的可能变化。
在实际传输过程中,PMTUD会在这几种状态之间进行切换,以适应网络状况的变化。
(3) ICMP差错报文:PMTUD依赖以下两种ICMP差错报文:
-
"Fragmentation Needed and DF Set" (Type 3, Code 4)
:当数据包长度超过下一跳MTU且设置了DF标志时,中间设备会返回这个差错报文,并在报文中携带下一跳MTU值。 -
"Packet Too Big" (Type 2, Code 0)
:当IPv6数据包长度超过下一跳MTU时,中间设备会返回这个差错报文,也会携带下一跳MTU值。
发送方需要正确解析这两种差错报文,并及时调整TCP报文段大小,以保证PMTUD的正常工作。
实践经验:
-
一些防火墙或者NAT设备可能会过滤ICMP差错报文,导致PMTUD无法工作。解决办法是在这些设备上开启ICMP差错报文的转发,或者使用TCP选项中的MSS值来限制报文段大小。
-
如果网络中存在MTU值很小的链路(如PPPoE、VPN等),可能会导致TCP性能下降。解决办法是在TCP连接建立时,使用较小的MSS值,避免过大的报文段。
-
在某些网络环境下,中间设备可能不会发送ICMP差错报文,导致PMTUD失效。解决办法是使用TCP选项中的MSS值来限制报文段大小,或者使用基于探测的PMTUD方法(如PLPMTUD)。
-
为了避免PMTUD过程中的延迟和丢包,一些实现会缓存已发现的路径MTU值,并在后续连接中直接使用,以加快收敛速度。
TCP路径MTU发现是一种自适应调整报文段大小的机制,通过与ICMP差错报文的交互,发现当前路径的MTU值,并动态调整TCP报文段大小,在不产生IP分片的情况下最大化传输效率。
3.2 TCP状态转换
TCP状态转换图是描述TCP连接建立、数据传输和连接释放过程中,TCP连接所经历的各种状态以及状态之间转换关系的一种图形表示。它直观地展示了TCP协议的工作流程和状态管理机制。
在TCP状态转移图中,有几个典型的过程值得特别关注,它们体现了TCP协议的核心功能和特性。同时,RFC协议规定和实际的套接字实现(如伯克利套接字)之间也存在一些差异。
(1) LISTEN状态的处理:RFC 793中,LISTEN状态是一个显式的状态,当应用程序调用listen()
函数时,TCP进入LISTEN状态,等待客户端连接。在伯克利套接字实现中,LISTEN状态是一个隐式的状态,当应用程序调用socket()
函数创建套接字时,就自动进入了LISTEN状态,无需显式调用listen()
函数。
(2) SYN_SENT状态的处理:RFC 793中,当TCP发送SYN报文后,会进入SYN_SENT状态,等待对方的SYN+ACK报文。如果收到的是对方的SYN报文(而非SYN+ACK),TCP会回复SYN+ACK报文,并进入SYN_RCVD状态。
在伯克利套接字实现中,如果TCP在SYN_SENT状态收到对方的SYN报文,会直接进入ESTABLISHED状态,而不经过SYN_RCVD状态。这种行为称为"同时打开(simultaneous open)"。
同时打开在实际网络中较为罕见,但在某些场景下(如P2P网络)可能会发生。应用程序需要正确处理这种情况,以避免连接异常。
(3) FIN_WAIT_2状态的处理:RFC 793中,当TCP在FIN_WAIT_1状态收到对方的ACK报文后,会进入FIN_WAIT_2状态,等待对方的FIN报文。如果一直未收到FIN报文,TCP会持续停留在FIN_WAIT_2状态。
在伯克利套接字实现中,如果TCP在FIN_WAIT_2状态停留时间过长,会触发保活计时器,主动向对方发送探测报文,以确认连接状态。如果探测失败,TCP会直接进入CLOSED状态,而不再等待对方的FIN报文。
这种差异可以防止TCP连接长时间占用系统资源,提高了系统的稳定性和可用性。但也可能导致连接被意外关闭,应用程序需要合理设置保活计时器的阈值。
(4) TIME_WAIT状态的处理:RFC 793中,当TCP在TIME_WAIT状态等待2MSL超时后,就会直接进入CLOSED状态,连接彻底关闭。
在伯克利套接字实现中,为了优化服务器的性能和资源利用,引入了TIME_WAIT状态的快速回收机制。当服务器在短时间内需要大量创建和关闭连接时,可以通过设置SO_REUSEADDR选项,让新的连接重用处于TIME_WAIT状态的端口,而无需等待2MSL超时。
这种优化可以显著提高服务器的并发处理能力,但也可能引入一些安全隐患(如端口劫持),需要谨慎使用。
(5) CLOSE_WAIT状态的处理:RFC 793中,当TCP收到对方的FIN报文后,会进入CLOSE_WAIT状态,等待应用程序主动关闭连接。
在伯克利套接字实现中,如果应用程序一直不关闭连接,TCP会持续停留在CLOSE_WAIT状态,占用系统资源。为了防止这种情况,一些实现会引入半关闭连接的概念,允许应用程序单向关闭连接,而无需等待对方的FIN报文。
半关闭连接可以提高资源利用效率,但也增加了应用程序的复杂性,需要仔细设计和实现。
3.3 重置报文段
TCP重置报文段(RST)是一种特殊的TCP报文,用于异常终止一个TCP连接。当出现某些错误情况时,TCP会发送RST报文,立即关闭连接,而不经过正常的四次挥手过程。
(1) 针对不存在端口的连接请求:当一个TCP客户端向服务器发送连接请求(SYN报文)时,如果服务器上没有相应的端口在监听,服务器就会返回一个RST报文,告知客户端连接请求被拒绝。这种情况通常发生在以下场景:
- 服务器端口未打开或者服务进程未启动。
- 客户端连接请求的目的端口号错误。
- 服务器端口被防火墙或者安全策略阻止。
通过RST报文,服务器可以快速向客户端通知连接请求失败,避免客户端长时间等待。
(2) 终止一个已建立的连接:在某些情况下,需要立即终止一个已经建立的TCP连接,而不能等待正常的四次挥手过程完成。这时,可以通过发送RST报文来强制关闭连接。常见的场景包括:
- 应用程序异常退出或者崩溃,来不及正常关闭连接。
- 检测到连接上有非法或者恶意的数据传输。
- 因为网络故障或者系统错误,连接状态出现不一致。
当一方发送RST报文后,连接将立即进入CLOSED状态,不再发送或者接收任何数据。
(3) 处理半开连接:半开连接是指一端认为连接已经关闭,而另一端认为连接还在维持的情况。这通常发生在以下场景:
- 一方异常关闭连接(如断电、崩溃等),而没有发送FIN报文。
- 一方发送的FIN报文在网络中丢失,未能到达对端。
- 一方关闭连接后,另一方仍然向其发送数据。
当出现半开连接时,仍然维持连接的一方会收到对端发来的RST报文,从而意识到连接已经关闭,进入CLOSED状态。这样可以避免半开连接长时间占用系统资源。
(4) 处理TIME_WAIT状态错误:在TCP四次挥手过程中,主动关闭连接的一方会进入TIME_WAIT状态,等待2MSL超时,以确保对端收到了最后的ACK报文。如果在TIME_WAIT状态时,又收到了对端发来的数据报文,就会出现TIME_WAIT状态错误。这时,主动关闭方会发送RST报文,强制关闭连接,防止新旧数据包混淆。
(5) 处理序列号错误:TCP通过序列号来保证数据的可靠传输和有序接收。如果一方收到的数据报文的序列号不在期望的窗口范围内,就会发送RST报文,强制关闭连接,防止错误数据的传输。这种情况通常发生在以下场景:
- 网络中存在重复的数据报文,导致序列号错乱。
- 一方的接收缓存溢出,无法接收新的数据。
- 一方因为系统错误,发送了序列号错误的数据报文。
通过RST报文,可以及时终止异常的连接,避免错误数据的传输和处理。
3.4 与TCP连接相关的攻击
TCP作为互联网上最广泛使用的传输层协议,虽然提供了可靠、有序的数据传输服务,但也存在一些安全漏洞和攻击风险。
(1) SYN泛洪攻击(SYN Flooding):
-
攻击原理:攻击者发送大量的SYN连接请求报文,但不完成三次握手过程,导致服务器上积累大量的半开连接(SYN_RECV状态),耗尽服务器的资源和内存,使其无法响应正常的连接请求。
-
防范方法:
- 启用SYN Cookie机制,对每个SYN请求编码一个Cookie,只有收到合法的ACK报文才分配连接资源。
- 限制SYN_RECV状态的连接数量,超过阈值就丢弃新的SYN请求。
- 缩短SYN_RECV状态的超时时间,尽快释放半开连接占用的资源。
- 使用防火墙或者入侵检测系统(IDS)检测和过滤异常的SYN请求。
(2) TCP复位攻击(TCP Reset Attack):
-
攻击原理:攻击者伪造RST报文,发送给连接的一方,导致连接异常关闭。攻击者通过猜测或者嗅探获得连接的序列号和端口号,从而构造出合法的RST报文。
-
防范方法:
- 启用TCP时间戳选项,在RST报文中携带时间戳信息,防止伪造的RST报文被接受。
- 使用加密协议(如SSL/TLS)对TCP连接进行保护,防止连接信息被嗅探和伪造。
- 对RST报文进行合法性验证,如检查序列号是否在合理范围内,防止伪造的RST报文被接受。
- 使用防火墙或者IDS检测和过滤异常的RST报文。
(3) TCP会话劫持(TCP Session Hijacking):
-
攻击原理:攻击者通过嗅探或者猜测获得连接的序列号和端口号,伪造数据包插入到连接中,从而劫持会话,冒充合法用户进行非法操作。
-
防范方法:
- 使用加密协议(如SSL/TLS)对TCP连接进行保护,防止连接信息被嗅探和伪造。
- 启用TCP MD5选项,对TCP报文进行完整性验证,防止伪造的数据包被接受。
- 使用强壮的身份认证机制(如双因素认证)验证用户身份,防止会话被劫持后的非法操作。
- 限制连接的生命周期,定期更新会话密钥,减少会话劫持的风险。
(4) TCP欺骗攻击(TCP Spoofing):
-
攻击原理:攻击者伪造TCP报文的源IP地址,欺骗服务器与其建立连接,从而绕过IP地址验证,进行非法操作。
-
防范方法:
- 在服务器上启用严格的反向路径过滤(RPF)机制,验证数据包的源IP地址是否合法。
- 使用加密协议(如SSL/TLS)对TCP连接进行保护,防止连接信息被伪造。
- 在应用层实现强壮的身份认证和授权机制,验证用户身份和权限。
- 使用防火墙或者IDS检测和过滤伪造的TCP报文。
(5) TCP小值MSS攻击(TCP MSS Attack):
-
攻击原理:攻击者故意在TCP连接建立过程中,发送一个很小的MSS(Maximum Segment Size)值,导致后续数据传输中出现大量的小包,增加服务器的处理开销和网络拥塞。
-
防范方法:
- 在服务器上设置合理的最小MSS值,拒绝过小的MSS请求。
- 限制单个连接的数据包数量和频率,防止小包攻击耗尽服务器资源。
- 使用流量整形和限速机制,控制单个连接的带宽和数据包速率。
- 使用防火墙或者IDS检测和过滤异常的MSS值。
与TCP相关的攻击种类繁多,涉及连接建立、数据传输、连接释放等各个阶段。攻击者利用TCP协议的特性和缺陷,试图耗尽服务器资源、窃取敏感信息、劫持会话控制等。为了防范这些攻击,我们需要采取多层次、全方位的安全措施,包括加密通信、身份认证、完整性验证、访问控制、异常检测等。同时,也要加强网络基础设施的安全性,如防火墙、IDS、路由器等设备的配置和管理。
相关文章:
网络运输层之(1)TCP连接管理
网络运输层之(1)TCP连接管理 Author: Once Day Date: 2024年10月22日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: 通信网络技术_Once-Day的博客…...
基于阿里云服务器部署静态的website
目录 一:创建服务器实例并connect 二:本地文件和服务器share 三:关于IIS服务器的安装预配置 四:设置安全组 五:建站流程 六:关于备案 一:创建服务器实例并connect 创建好的服务器实例在云…...
Git项目管理
Git项目管理 分区概念:创建本地仓库查看当前仓库的状态工作区添加到暂存区暂存区恢复到工作区工作区提交到本地仓库查看提交日志版本回滚查看版本变更的所有记录分支查看分支创建分支删除分支切换分支合并分支 冲突解决HEAD指针分支使用的一般规范masterdevelopfeat…...
实践指南:EdgeOne与HAI的梦幻联动
在当今快速发展的数字时代,安全和速度已成为网络服务的基石。EdgeOne,作为腾讯云提供的边缘安全加速平台,以其全球部署的节点和强大的安全防护功能,为用户提供了稳定而高效的网络体验。而HAI(HyperApplicationInventor…...
OmniDiskSweeper :一款专为 macOS 设计的磁盘使用分析工具
OmniDiskSweeper 是一款专为 macOS 设计的磁盘使用分析工具,由 The Omni Group 开发。它的主要目的是帮助用户可视化磁盘上的文件和文件夹,并找出占用大量空间的文件,从而帮助用户释放磁盘空间。 OmniDiskSweeper 的特点包括: 简…...
【Git】:Git基本操作
目录 创建、配置本地仓库 创建本地仓库 配置本地仓库 认识工作区、暂存区、版本库 修改文件 版本回退 撤销修改 删除文件 创建、配置本地仓库 创建本地仓库 我们通常可以通过以下两种方式之一获取 Git 存储库: 自己在本地目录创建一个本地仓库 从其它服务…...
C++设计模式:建造者模式(Builder) 房屋建造案例
什么是建造者模式? 建造者模式是一种创建型设计模式,它用于一步步地构建一个复杂对象,同时将对象的构建过程与它的表示分离开。简单来说: 它将复杂对象的“建造步骤”分成多部分,让我们可以灵活地控制这些步骤。通过…...
由于centos停更,yum、docker等不支持,采用阿里云仓库搭建K8S
一:准备 服务器信息主机名IP地址Centos7.9node1-master192.168.35.130Centos7.9node2192.168.35.131 # 查看系统版本 cat /etc/centos-release # 查看内核版本 uname -sr二:服务器前置操作 每个节点都需要操作 #使用 hostnamectl set-hostname设置主机…...
cocos creator 3.8 一些简单的操作技巧,材质的创建 1
这是一个飞机的3D模型与贴图 导入到cocos中,法线模型文件中已经包含了mesh、material、prefab,也就是模型、材质与预制。界面上创建一个空节点Plane,将模型直接拖入到Plane下。新建材质如图下 Effect属性选择builtin-unlit,不需…...
下载安装Android Studio
(一)Android Studio下载地址 https://developer.android.google.cn/studio 滑动到 点击下载文档 打开新网页 切换到english 
随着人口老龄化进程的加速,摔倒事故逐渐成为威胁老年人健康和安全的主要问题之一。研究表明,摔倒不仅可能导致老年人骨折、头部受伤等严重的身体损伤,还可能引发心理恐惧和行动能力下降,从而降低其生活质量和独立性。如何快速、准…...
C++特殊类设计(不能被拷贝的类、只能在堆上创建对象的类、不能被继承的类、单例模式)
C特殊类设计 在实际应用中,可能需要设计一些特殊的类对象,如不能被拷贝的类、只能在堆上创建对象的类、只能在栈上创建对象的类、不能被继承的类、只能创建一个对象的类(单例模式)。 1. 不能被拷贝的类 拷贝只会发生在两个场景…...
Javaweb前端HTML css 整体布局
最后一个是线条颜色 盒子,整体还是300,400...
数据集-目标检测系列- 花卉 鸡蛋花 检测数据集 frangipani >> DataBall
数据集-目标检测系列- 花卉 鸡蛋花 检测数据集 frangipani >> DataBall DataBall 助力快速掌握数据集的信息和使用方式,会员享有 百种数据集,持续增加中。 贵在坚持! 数据样例项目地址: * 相关项目 1)数据集…...
【从零开始的LeetCode-算法】3297. 统计重新排列后包含另一个字符串的子字符串数目 I
给你两个字符串 word1 和 word2 。 如果一个字符串 x 重新排列后,word2 是重排字符串的 前缀,那么我们称字符串 x 是 合法的 。 请你返回 word1 中 合法 子字符串的数目。 示例 1: 输入:word1 "bcca", word2 "…...
【Redis_Day5】String类型
【Redis_Day5】String类型 String操作String的命令set和get:设置、获取键值对mset和mget:批量设置、获取键值对setnx/setex/psetexincr和incrby:对字符串进行加操作decr/decrby:对字符串进行减操作incrbyfloat:浮点数加…...
【CVE-2024-48694】OfficeWeb365 SaveDraw
漏洞描述 OfficeWeb365 v.8.6.1.0和v7.18.23.0中的文件上传漏洞允许远程攻击者通过pw/savedraw组件执行任意代码。 影响版本: V8.6.1.0; V7.18.23.0 网络测绘 “OfficeWeb365” 漏洞信息 POST /PW/SaveDraw?path../../Content/img&idx6.ashx H…...
leecode134.加油站
一开始想的是总体上加油量超过耗油量那么就一定能找到一个起始点可以跑一圈,这个起始点选择补充油量与耗油量差值最大的那gas个点,但是我没仔细审题,这个起始点是索引逐次1绕一圈而不是随便选择,gas[5,8,2,8],cost[6,5…...
分层架构 IM 系统之 Entry 部署模式
在前面的一篇技术短文(分层架构 IM 系统之架构解读)中,对【分层架构】进行了详细分析;今天我们聊一下【入口层】Entry 的部署模式。 Entry 作为 IM 系统整个后端集群的入口,直接与客户端建立 TCP 长连接,E…...
【Java从入门到放弃 之 多线程 四】
多线程 四 多线程 四读写锁的使用代码演示 乐观锁的使用代码演示 信号量代码演示 倒计时门禁代码演示 循环栅栏Condition详解代码案例 多线程 四 读写锁的使用 上一篇我们介绍到了可重入锁,现在我们来介绍读写锁。实际上,使用可重入锁的时候我们就可以…...
OpenHarmony-3.驱动HDF
OpenHarmony HDF 框架 1.OpenHarmony HDF 框架概述 OpenHarmony驱动子系统采用C面向对象编程模型构建,通过平台解耦、内核解耦,兼容不同内核,提供了归一化的驱动平台底座,旨在为开发者提供更精准、更高效的开发环境,力…...
udp_socket
文章目录 UDP服务器封装系统调用socketbind系统调用bzero结构体清0sin_family端口号ip地址inet_addrrecvfromsendto 新指令 netstat -naup (-nlup)包装器 的两种类型重命名方式包装器使用统一可调用类型 关键字 typedef 类型重命名系统调用popen关于inet_ntoa UDP服务器封装 系…...
Java NIO 核心知识总结
在学习 NIO 之前,需要先了解一下计算机 I/O 模型的基础理论知识。还不了解的话,可以参考我写的这篇文章:Java IO 模型详解。 一、NIO 简介 在传统的 Java I/O 模型(BIO)中,I/O 操作是以阻塞的方式进行的。…...
音频信号采集前端电路分析
音频信号采集前端电路 一、实验要求 要求设计一个声音采集系统 信号幅度:0.1mVpp到1Vpp 信号频率:100Hz到16KHz 搭建一个带通滤波器,滤除高频和低频部分 ADC采用套件中的AD7920,转换率设定为96Ksps ;96*161536 …...
PyTorch基础学习03_数学运算自动微分
目录 一、数学运算 1、基本操作 2、三角函数 3、统计学函数 二、保存和加载 三、并行化 四、自动微分 1、相关概念 2、计算梯度 1.标量梯度计算 2.向量梯度计算 3.多标量梯度计算 4.多向量梯度计算 5.矩阵梯度计算 3、梯度上下文控制 1、梯度控制 2、梯度更新…...
HarmonyOS4+NEXT星河版入门与项目实战(16)------ 状态管理 @State(页面数据刷新与渲染)
文章目录 1、@State装饰器2、视图渲染演示1、无嵌套的对象属性值变化时可以触发页面渲染2、嵌套对象的嵌套属性值变化时不能够触发页面刷新渲染3、数组中对象的属性值变化时不能触发页面刷新渲染3、总结1、@State装饰器 2、视图渲染演示 常规的 string、number 这里就不演示了…...
K8s 一键部署 MongoDB 的 Replica-Set 和 MongoDB-Express
什么是 MongoDB 副本集? MongoDB 副本集(Replica-Set)是一个分布式数据库系统,它包含一个主节点和多个从节点。主节点负责处理所有写操作,从节点用于读取数据。当主节点发生故障时,从节点可以自动选举一个…...
React Native的界面与交互
React Native (RN) 是一个由 Facebook 开发的开源框架,用于构建跨平台的移动应用程序。它允许开发者使用 JavaScript 和 React 来创建原生 iOS 和 Android 应用。RN 的出现极大地简化了移动应用的开发过程,使得开发者可以更快速、更高效地构建高质量的应…...
【探寻密码的奥秘】-001:解开密码的神秘面纱
目录 1、密码学概述1.1、概念1.2、目的1.3、应用场景 2、密码学的历史2.1、第一时期:古代密码时代2.2、第二时期:机械密码时代2.3、第三时期:信息密码时代2.4、第四时期:现代密码时代 3、密码学的基本概念3.1、一般通信系统3.2、保…...
C++实现Raft算法
概念部分 Raft 算法是一种用于实现分布式系统中的一致性的算法。它是为了容易理解而设计的,其目标是实现和 Paxos 算法相同的功能,但更加容易理解和实现。Raft 算法在分布式系统中尤其关键,因为它帮助系统中的多个节点就其数据的准确状态达成…...
FastApi教程
FastAPI框架 fastapi,一个用于构建 API 的现代、快速(高性能)的web框架。 fastapi是建立在Starlette和Pydantic基础上的,Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/…...
HTB:WifineticTwo[WriteUP]
目录 连接至HTB服务器并启动靶机 信息搜集 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机开放端口进行脚本、服务扫描 使用curl访问靶机8080端口 使用浏览器直接访问/login路径 漏洞利用 使用searchsploit搜索该WebAPP漏洞 Payload USER_FLAG:bb…...
ubuntu16.04在ros使用USB摄像头-解决could not open /dev/video0问题
首先检查摄像头 lsusb 安装 uvc camera 功能包 sudo apt-get install ros-indigo-uvc-camera 安装 image 相关功能包 sudo apt-get install ros-kinetic-image-* sudo apt-get install ros-kinetic-rqt-image-view运行 uvc_camera 节点 首先输入roscore 然后另外开一个终端输入…...
大模型专栏--什么是大模型
什么是大模型 来自 chatGPT 的回答: “大模型”通常指的是在机器学习和深度学习领域,尤其是自然语言处理(NLP)和计算机视觉(CV)中,具有大量参数和复杂结构的模型。这些模型通常需要大量的数据和…...
LLaMA-Mesh: Unifying 3D Mesh Generation with Language Models 论文解读
目录 一、概述 二、相关工作 1、LLMs到多模态 2、3D对象生成 3、自回归的Mesh生成 三、LLaMA-Mesh 1、3D表示 2、预训练模型 3、有监督的微调数据集 4、数据集演示 四、实验 1、生成的多样性 2、不同模型text-to-Mesh的比较 3、通用语境的评估 一、概述 该论文首…...
golang实现TCP服务器与客户端的断线自动重连功能
1.服务端 2.客户端 生成服务端口程序: 生成客户端程序: 测试断线重连: 初始连接成功...
项目实战:基于深度学习的人脸表情识别系统设计与实现
大家好,人脸表情识别是计算机视觉领域中的一个重要研究方向,它涉及到对人类情感状态的理解和分析。随着深度学习技术的发展,基于深度学习的人脸表情识别系统因其高精度和强大的特征学习能力而受到广泛关注。本文旨在探讨基于深度学习的人脸表…...
【mongodb】社区版8:改变配置bindip和授权
更改配置 sudo systemctl restart mongod (base) root@k8s-master-pfsrv:/home/zhangbin# sudo tail -n 20 /var/log/mongodb/mongod.log 日志感觉是成功了:{"t":{"$date":"2024-11-19T19:57:47.076+08:00"...
python入门9-函数基础
函数介绍 <1>什么是函数 请看如下代码: print(" _ooOoo_ ") print(" o8888888o ") print(" 88 . 88 ") print(" …...
AMD(Xilinx) FPGA配置Flash大小选择
目录 1 FPGA配置Flash大小的决定因素2 为什么选择的Flash容量大小为最小保证能够完成整个FPGA的配置呢? 1 FPGA配置Flash大小的决定因素 在进行FPGA硬件设计时,选择合适的配置Flash是我们进行硬件设计必须考虑的,那么配置Flash大小的选择由什…...
TypeScript学习笔记(二)
接一 四、类型声明 使用 : 来对变量或函数形参,进行类型声明: let a: string //变量a只能存储字符串 let b: number //变量b只能存储数值 let c: boolean //变量c只能存储布尔值 a hello a 100 //警告:不能将类型“number”分配给类型“…...
Centos Stream 9安装Jenkins-2.485 构建自动化项目步骤
官网:https://www.jenkins.io/ 1 下载 环境准备: 版本支持查询:https://pkg.jenkins.io/redhat-stable/ 安装JDK17:https://blog.csdn.net/qq_44870331/article/details/140784297 yum -y install epel-release wget upgradew…...
多目标粒子群优化(Multi-Objective Particle Swarm Optimization, MOPSO)算法
概述 多目标粒子群优化(MOPSO) 是粒子群优化(PSO)的一种扩展,用于解决具有多个目标函数的优化问题。MOPSO的目标是找到一组非支配解(Pareto最优解),这些解在不同目标之间达到平衡。…...
【网络系统管理】2023年全国职业院校技能大赛:组策略--10套题组合--1
1、限制访问C盘; (1)搜索《我的电脑》 (2)用户配置\策略\管理模板\Windows组件\文件资源管理器 2、禁止运行run.exe; (1)搜索《应用程序》 (2)用户配置\策略\管理模板\系统...
【Golang】——Gin 框架中的 API 请求处理与 JSON 数据绑定
在现代 Web 开发中,API(特别是 RESTful API)是前后端分离架构的核心。Gin 框架提供了丰富的功能来处理 API 请求和 JSON 数据,使得开发者可以快速构建高效的接口服务。本篇博客将从基础到深入,全面讲解如何使用 Gin 框…...
在Linux下配置gitee与Github的远程仓库
目录 前言 云服务器下载git 检测是否下载成功git Linux下配置gitee远程仓库 代码提交演示 git三板斧 Linux下配置Github远程仓库 最后的提醒 前言 那么本篇文章将是在,你已经创建了本地仓库的基础上,在Linux下配置gitee的远程仓库的步骤ÿ…...
自动化测试过程操作细节
一、软件与框架介绍 1. Postman 读音:[pəʊstmən](剖斯特曼) 介绍:API开发与测试的得力助手,通过直观界面发送HTTP请求,查看响应数据。支持环境变量、集合、脚本等功能。 主要特点:易于使用…...
iic协议
IIC(Inter-Integrated Circuit)协议,也被称为I2C协议,是一种由荷兰的PHILIPS公司(现为NXP半导体公司)开发的简单、高效的通信协议。以下是关于IIC协议的详细介绍: 一、IIC协议概述 定义&#…...