V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
yujianwjj
V2EX  ›  Linux

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

  •  
  •   yujianwjj · 260 天前 · 2011 次点击
    这是一个创建于 260 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

    tcp 发送是滑动窗口内的数据以不超过 mss 进行顺序发送,等到对方 ack 后调整滑动窗口或者进行重传
    jackniu
        26
    jackniu  
       259 天前
    @hankai17 每次软中断都是独立的线程在处理,不存在多队列拿错的情况,因为一个软中断和一个硬中断是一一对应的
    neoblackcap
        27
    neoblackcap  
       259 天前
    自己在写协议栈或者网卡驱动么?应用层开发者不应该关心这个 TCP 层的实现细节。因为从接收端会重排,tcp socket 读出来的东西必然是有序的。
    然后如果是想稳定复现这个两个 IP 包的先后顺序大概是很难,因为你必须控制传输链路中的全部网络设备,否则都没法实现稳定丢包。
    如果要尝试复现,可以在网络链路中的一台网络设备进行设置,通过类似 eBPF 或者防火墙技术,对包进行过滤
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   889 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 21:00 · PVG 05:00 · LAX 14:00 · JFK 17:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.