Distributions
› Ubuntu
› Fedora
› CentOS
中文资源站
› 网易开源镜像站
yujianwjj
V2EX  ›  Linux

请教一个 tcp 超过 mss 分包的问题

  •  
  •   yujianwjj · Aug 11, 2023 · 3858 views
    This topic created in 1186 days ago, the information mentioned may be changed or developed.

    假设一个 tcp 报文的大小是 1600 ,然后 mss 是 1440 ,那么协议栈会分包,分成 0-1440 ,1440-1600 两个包发出。

    现在遇到一个问题是,有的机器上是先发出 0-1440 的包再发送 1440-1600 的包,有的机器是先发出 1440-1600 的包再发送 0-1440 的包。

    这个是可以配置的吗?怎么设置?

    27 replies  •  2023-08-13 00:38:06 +08:00
    hankai17
    hankai17
    Aug 11, 2023
    1
    粘包警察在此
    ovtfkw
    ovtfkw
    Aug 11, 2023 via iPhone
    2
    粘包了吧
    ysc3839
    ysc3839
    Aug 11, 2023 via Android
    3
    TCP 之上传输的是数据流,你说的“报文的大小是 1600”应该是指“一次性发送了 1600 字节”,因为 MSS 是 1440 ,所以不能只用一个 TCP 包发完。那按理来说 TCP 会先发前面的数据,再发后面的数据,因为接收端收到后要保持顺序,先收到后面的还得等前面的,没有好处。
    cheng6563
    cheng6563
    Aug 11, 2023❤️1
    4
    等你网络差点就会发现数据可能是 0-200 一个包过来的了
    yujianwjj
    yujianwjj
    OP
    Aug 11, 2023
    5
    补充一下:我是在发送端用 tcpdump 抓包查看的。
    coderxy
    coderxy
    Aug 11, 2023❤️1
    6
    楼上都是些啥,开口闭口粘包的。 这就是一个基本的 TCP 分段问题, 分段之后接收方系统内核会帮你处理好顺序然后再写到你的进程的接收缓冲区。 至于能不能改变发送顺序,可能会比较麻烦,你可以尝试使用 tc 随机丢包去模拟 0-1440 的报文丢弃了后,1440-1600 先到,0-1440 通过重发后到的情况,对于接收方来说,效果是一样的。
    hankai17
    hankai17
    Aug 11, 2023
    7
    没看过相关源码
    怀疑是网卡多队列 包被拆分后 送到不同队列对应不同的发送线程 造成发包乱序?
    coderxy
    coderxy
    Aug 11, 2023
    8
    @coderxy 补充一下,没看清楼主的问题,你这个顺序每台机器每次都固定吗? 系统相同吗? 确实没遇到过。
    iOCZ
    iOCZ
    Aug 11, 2023
    9
    发送顺序并不重要,每个包会有一个序号吧,收到的时候放入缓冲区就有序了。
    Exxfire
    Exxfire
    Aug 11, 2023
    10
    从后往前发是一种不好的操作。所以怀疑:
    1. 是不是底层用了什么并行的方式发送数据,导致大 buf 处理更慢;
    2. 是不是抓了大包的重传包;
    3. 我更喜欢 wireshark 。
    yujianwjj
    yujianwjj
    OP
    Aug 11, 2023 via iPhone
    11
    补充:不同机器的硬件是不同,每台机器都是固定的顺序,操作系统都是 linux ,但是内核版本不一致
    kkkbbb
    kkkbbb
    Aug 11, 2023
    12
    你是单纯的想让发的顺序一致,还是因为这个导致了什么问题?即便发的顺序不一致,tcp 接收端也会顺序重组数据啊,接收端没啥问题吧
    inhzus
    inhzus
    Aug 11, 2023
    13
    tcpdump 看到的顺序和 receiver 观测到的顺序不一定一致啊...
    leonshaw
    leonshaw
    Aug 11, 2023 via Android
    14
    不正常,乱序很容易触发快速重传
    julyclyde
    julyclyde
    Aug 11, 2023
    15
    首先,不能用报文这个词
    只能说“在 TCP 流上发送了一个 1600 长度的消息”

    你说的“先发出 1440-1600”这个无所谓,反正对方收到的是保证顺序的
    neroxps
    neroxps
    Aug 11, 2023 via iPhone
    16
    两边抓包对比下,发包方没收到重传要求就不需要管他。
    julyclyde
    julyclyde
    Aug 11, 2023
    17
    @neroxps 即使收到重传请求也不用管啊
    zerofiny
    zerofiny
    Aug 11, 2023
    18
    每次握手就获取目前能使用的 MTU 大小, 一般这个大小是减去 以太网头 16byte
    每次发送的数据 = MTU - IP header size - tcp header size
    内核数据接收 会根据包的 seq 等计算等计算包的位置 保障在用户端不会乱序
    neroxps
    neroxps
    Aug 11, 2023 via iPhone
    19
    @julyclyde 大量重传请求是需要排查的
    yolee599
    yolee599
    Aug 11, 2023 via Android
    20
    你是在发送端抓包的还是在接收端抓包的,一般发送端是按顺序发送的,但接收端不一定是按顺序收到的,因为两个包走了不一样的网络路径
    r6cb
    r6cb
    Aug 11, 2023
    21
    或许可以给第一个包的 URG 置 1 ,能让它不排队
    zhs227
    zhs227
    Aug 11, 2023
    22
    tcp 分段以后头部是有标记是否第 1 片和是否最后一片的。这是基本操作
    zhs227
    zhs227
    Aug 11, 2023
    23
    看错了,tcp 是没有分片标记的,ip 层才有。上一楼回答有误。
    ZRS
    ZRS
    Aug 12, 2023
    24
    伪需求,如果你需要任意控制发送量和顺序,请用 UDP 。但接收方也是不保序的
    BingoXuan
    BingoXuan
    Aug 12, 2023
    25
    发送永远都是按顺序的,就是 0:1440,1440:1600 这样。如果接收端 0:1440 没收到,而收到了 1440:1600 ,会发送快速重传,让发送端重新发送 0:1440 。

    tcp 发送是滑动窗口内的数据以不超过 mss 进行顺序发送,等到对方 ack 后调整滑动窗口或者进行重传
    jackniu
    jackniu
    Aug 12, 2023
    26
    @hankai17 每次软中断都是独立的线程在处理,不存在多队列拿错的情况,因为一个软中断和一个硬中断是一一对应的
    neoblackcap
    neoblackcap
    Aug 13, 2023
    27
    自己在写协议栈或者网卡驱动么?应用层开发者不应该关心这个 TCP 层的实现细节。因为从接收端会重排,tcp socket 读出来的东西必然是有序的。
    然后如果是想稳定复现这个两个 IP 包的先后顺序大概是很难,因为你必须控制传输链路中的全部网络设备,否则都没法实现稳定丢包。
    如果要尝试复现,可以在网络链路中的一台网络设备进行设置,通过类似 eBPF 或者防火墙技术,对包进行过滤
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4691 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 73ms · UTC 03:20 · PVG 11:20 · LAX 19:20 · JFK 22:20
    ♥ Do have faith in what you're doing.