假设一个 tcp 报文的大小是 1600 ,然后 mss 是 1440 ,那么协议栈会分包,分成 0-1440 ,1440-1600 两个包发出。
现在遇到一个问题是,有的机器上是先发出 0-1440 的包再发送 1440-1600 的包,有的机器是先发出 1440-1600 的包再发送 0-1440 的包。
这个是可以配置的吗?怎么设置?
1
hankai17 2023-08-11 17:31:19 +08:00
粘包警察在此
|
2
ovtfkw 2023-08-11 17:33:38 +08:00 via iPhone
粘包了吧
|
3
ysc3839 2023-08-11 17:41:13 +08:00 via Android
TCP 之上传输的是数据流,你说的“报文的大小是 1600”应该是指“一次性发送了 1600 字节”,因为 MSS 是 1440 ,所以不能只用一个 TCP 包发完。那按理来说 TCP 会先发前面的数据,再发后面的数据,因为接收端收到后要保持顺序,先收到后面的还得等前面的,没有好处。
|
4
cheng6563 2023-08-11 17:42:27 +08:00 1
等你网络差点就会发现数据可能是 0-200 一个包过来的了
|
5
yujianwjj OP 补充一下:我是在发送端用 tcpdump 抓包查看的。
|
6
coderxy 2023-08-11 17:53:48 +08:00 1
楼上都是些啥,开口闭口粘包的。 这就是一个基本的 TCP 分段问题, 分段之后接收方系统内核会帮你处理好顺序然后再写到你的进程的接收缓冲区。 至于能不能改变发送顺序,可能会比较麻烦,你可以尝试使用 tc 随机丢包去模拟 0-1440 的报文丢弃了后,1440-1600 先到,0-1440 通过重发后到的情况,对于接收方来说,效果是一样的。
|
7
hankai17 2023-08-11 17:59:05 +08:00
没看过相关源码
怀疑是网卡多队列 包被拆分后 送到不同队列对应不同的发送线程 造成发包乱序? |
9
iOCZ 2023-08-11 18:03:50 +08:00
发送顺序并不重要,每个包会有一个序号吧,收到的时候放入缓冲区就有序了。
|
10
Exxfire 2023-08-11 18:06:35 +08:00
从后往前发是一种不好的操作。所以怀疑:
1. 是不是底层用了什么并行的方式发送数据,导致大 buf 处理更慢; 2. 是不是抓了大包的重传包; 3. 我更喜欢 wireshark 。 |
11
yujianwjj OP 补充:不同机器的硬件是不同,每台机器都是固定的顺序,操作系统都是 linux ,但是内核版本不一致
|
12
kkkbbb 2023-08-11 18:17:36 +08:00
你是单纯的想让发的顺序一致,还是因为这个导致了什么问题?即便发的顺序不一致,tcp 接收端也会顺序重组数据啊,接收端没啥问题吧
|
13
inhzus 2023-08-11 18:38:33 +08:00
tcpdump 看到的顺序和 receiver 观测到的顺序不一定一致啊...
|
14
leonshaw 2023-08-11 18:44:29 +08:00 via Android
不正常,乱序很容易触发快速重传
|
15
julyclyde 2023-08-11 18:55:16 +08:00
首先,不能用报文这个词
只能说“在 TCP 流上发送了一个 1600 长度的消息” 你说的“先发出 1440-1600”这个无所谓,反正对方收到的是保证顺序的 |
16
neroxps 2023-08-11 19:41:09 +08:00 via iPhone
两边抓包对比下,发包方没收到重传要求就不需要管他。
|
18
hasdream 2023-08-11 19:47:21 +08:00
每次握手就获取目前能使用的 MTU 大小, 一般这个大小是减去 以太网头 16byte
每次发送的数据 = MTU - IP header size - tcp header size 内核数据接收 会根据包的 seq 等计算等计算包的位置 保障在用户端不会乱序 |
20
yolee599 2023-08-11 21:20:32 +08:00 via Android
你是在发送端抓包的还是在接收端抓包的,一般发送端是按顺序发送的,但接收端不一定是按顺序收到的,因为两个包走了不一样的网络路径
|
21
r6cb 2023-08-11 23:34:28 +08:00
或许可以给第一个包的 URG 置 1 ,能让它不排队
|
22
zhs227 2023-08-11 23:39:52 +08:00
tcp 分段以后头部是有标记是否第 1 片和是否最后一片的。这是基本操作
|
23
zhs227 2023-08-11 23:45:59 +08:00
看错了,tcp 是没有分片标记的,ip 层才有。上一楼回答有误。
|
24
ZRS 2023-08-12 02:41:25 +08:00
伪需求,如果你需要任意控制发送量和顺序,请用 UDP 。但接收方也是不保序的
|
25
BingoXuan 2023-08-12 12:55:17 +08:00
发送永远都是按顺序的,就是 0:1440,1440:1600 这样。如果接收端 0:1440 没收到,而收到了 1440:1600 ,会发送快速重传,让发送端重新发送 0:1440 。
tcp 发送是滑动窗口内的数据以不超过 mss 进行顺序发送,等到对方 ack 后调整滑动窗口或者进行重传 |
27
neoblackcap 2023-08-13 00:38:06 +08:00
自己在写协议栈或者网卡驱动么?应用层开发者不应该关心这个 TCP 层的实现细节。因为从接收端会重排,tcp socket 读出来的东西必然是有序的。
然后如果是想稳定复现这个两个 IP 包的先后顺序大概是很难,因为你必须控制传输链路中的全部网络设备,否则都没法实现稳定丢包。 如果要尝试复现,可以在网络链路中的一台网络设备进行设置,通过类似 eBPF 或者防火墙技术,对包进行过滤 |