go 分隔符处理粘包拆包问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
awanganddong

go 分隔符处理粘包拆包问题

  •  
  •   awanganddong Jul 12, 2023 2682 views
    This topic created in 1020 days ago, the information mentioned may be changed or developed.
    定义一个 buffer 来临时存放消息 从 conn 里面读取固定字节大小内容,判断当前内容里面有没有分隔符 如果没有找到分隔符,把当前内容追加到 buffer 里面,然后重复第 2 步 如果找到分隔符,把当前内容里面分隔符之前的内容追加到 buffer 后输出 然后重置 buffer ,把分隔符之后的内容追加到 buffer ,重复第 2 步 把分隔符之后的内容追加到 buffer 这个环节我不知道处理 package main import ( "bufio" "io" "log" "net" ) func main() { listener, err := net.Listen("tcp", "127.0.0.1:8866") if err != nil { log.Fatal(err) } defer listener.Close() for { con, err := listener.Accept() if err != nil { log.Println(err) continue } defer con.Close() reader := bufio.NewReader(con) for { data, err := reader.ReadSlice('\n') if err != nil { if err != io.EOF { // 分隔符之后 } else { //读取结束 break } } log.Println("received msg", len(data), "bytes:", string(data)) } } } package main import ( "log" "net" "time" ) func main() { conn, err := net.Dial("tcp", "127.0.0.1:8866") if err != nil { log.Fatal(err) } defer conn.Close() _, err = conn.Write([]byte("bbbb\ndfdfdfdfd")) if err != nil { panic(err) } time.Sleep(time.Second) } 
    21 replies    2023-08-03 20:54:09 +08:00
    ggvoking
        1
    ggvoking  
       Jul 12, 2023   2
    消息包头带个长度不就行了。
    awanganddong
        2
    awanganddong  
    OP
       Jul 12, 2023
    @ggvoking 主要是想搞明白采用分格符这种方式是怎么处理的
    itechify
        3
    itechify  
    PRO
       Jul 12, 2023 via Android   4
    粘包警察马上到!
    awanganddong
        4
    awanganddong  
    OP
       Jul 12, 2023
    TCP 流数据边界问题 这个没人吐槽了吧。
    LeegoYih
        5
    LeegoYih  
       Jul 12, 2023
    粘包警察来咯!

    可以参考一下这个项目处理边界的代码,他实现了好几种方式: https://github.com/go-netty/go-netty
    awanganddong
        6
    awanganddong  
    OP
       Jul 12, 2023
    bufio.NewReader 这个概念,理解错了。这个得出来的结果比较清晰一些
    ```
    func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:8866")
    if err != nil {
    log.Fatal(err)
    }
    defer conn.Close()
    _, err = conn.Write([]byte("bbbb\ndfdfdfdfd\nsdsdsd"))
    _, err = conn.Write([]byte("aaa\n"))
    if err != nil {
    panic(err)
    }
    time.Sleep(time.Second)
    }

    ```
    Vegetable
        7
    Vegetable  
       Jul 12, 2023
    你这个 TCP 结束之前,不会收到 EOF ,你就一直读不就行了吗,有什么需要处理的
    awanganddong
        8
    awanganddong  
    OP
       Jul 12, 2023
    这个文章可以参考

    消息长度固定,提前确定包长度,读取的时候也安固定长度读取,适合定长消息包。
    使用特殊的字符或字符串作为消息的边界,例如 HTTP 协议的 headers 以“\r\n”为字段的分隔符
    自定义协议,将消息分为消息头和消息体,消息头中包含表示消息总长度

    https://wangbjun.site/2019/coding/golang/golang-tcp-package.html

    谢谢各位
    Vegetable
        9
    Vegetable  
       Jul 12, 2023
    最后 err==EOF 的时候,data 是有值的,你不能直接丢掉,其他没什么问题
    awanganddong
        10
    awanganddong  
    OP
       Jul 12, 2023
    @Vegetable 好的,谢谢了。
    iceheart
        11
    iceheart  
       Jul 12, 2023 via Android
    一直收不到分隔符,内存不是要爆掉啦
    nightwitch
        12
    nightwitch  
       Jul 12, 2023
    这种方案也就在内网环境下用用,本质上和用换行符做分割没有什么区别。
    一旦被人摸清楚方案,无限给你发不带分割符的包,轻轻松松 oom
    deorth
        13
    deorth  
       Jul 12, 2023 via Android
    出警怎么这么慢啊
    rrfeng
        14
    rrfeng  
       Jul 12, 2023 via Android
    这种适合搞一个 ringbuffer
    MoYi123
        15
    MoYi123  
       Jul 13, 2023
    @nightwitch OOM 是另一个问题, http 协议的 content-length 也没有机制保证你不 oom 吧.
    itechify
        16
    itechify  
    PRO
       Jul 13, 2023 via Android
    @MoYi123 类似 nginx 的 client_max_body_size ,默认 0 无限制,设置最大长度,超过了就拒绝?
    mcfog
        17
    mcfog  
       Jul 13, 2023
    直接 bufio.NewScanner 搞定,用 https://pkg.go.dev/bufio#Scanner.Split 配置一个,分隔符策略几乎可以照抄默认的 ScanLines
    trzzzz
        18
    trzzzz  
       Jul 15, 2023
    @awanganddong 确实,像 scp 和 sftp 底层的实现都是基于 tcp 基础上自己规定客户端和服务端间的协议
    voidmnwzp
        19
    voidmnwzp  
       Jul 21, 2023 via iPhone
    建议用 CRLF 分割
    wkong
        20
    wkong  
       Jul 25, 2023
    分享一下我开源的单机百万的通用实时服务。里面有关于拆包分包这块。

    https://github.com/WuKongIM/WuKongIM
    ace12
        21
    ace12  
       Aug 3, 2023
    怎么还没有喷沾包的啊,我好难受
    About     Help     Advertise     Blog     API     FAQ     Solana     1072 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 430ms UTC 18:35 PVG 02:35 LAX 11:35 JFK 14:35
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86