V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
wuzhewuyou
V2EX  ›  Go 编程语言

go tcp 服务器,如何解包超大数据包

  •  
  •   wuzhewuyou · 2024-08-24 21:21:39 +08:00 · 2459 次点击
    这是一个创建于 370 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,据说论坛日经月经都是 TCP 粘包?

    参考了某论坛源码,直接贴链接不会被封号吧 某 csdn Golang 实现之 TCP 长连接-------服务端和客户端

    /article/details/131402492

    其中的解包核心代码

    //如果消息体超过 4096(默认长度) var pack []byte if length > 4096 { pack = make([]byte, 0, int(length-1)) readableLength := length - 1 for { if readableLength < 4096 { slice := make([]byte, readableLength) _, err = reader.Read(slice) pack = append(pack, slice...) break } slice := make([]byte, int32(reader.Buffered())) _, err = reader.Read(slice) pack = append(pack, slice...) //更新可读长度 readableLength = readableLength - int32(len(slice)) } // buffer 返回缓冲中现有的可读的字节数,2+length+1 表示帧类型+数据长度+帧尾 } else if length < 4096 && int32(reader.Buffered()) < length-1 { //退回已读取的帧头 reader.UnreadByte() return Msg{Type: 1}, errors.New("数据长度不足") } else { // 读取剩余帧内容 pack = make([]byte, int(length-1)) _, err = reader.Read(pack) if err != nil { return Msg{Type: 1}, err } }

    由于本人发送的消息体达到 2w ,进入第一个循环,打印出 len(slice),除了第一次有数据,后面 slice 长度全是 0 ,后面这个 pack 一直循环中,读取不到更多数据

    求解?数据哪里去了,怎样能取出?

    13 条回复    2024-08-25 18:27:17 +08:00
    yangxin0
        1
    yangxin0  
       2024-08-24 21:26:59 +08:00
    如果还停留在“粘包”这个概念,就该回去复习 computer network & TCP/IP 了,TCP 的抽象是 stream 也就是流,站在使用者的界面来看一定是流的 API 。
    wuzhewuyou
        2
    wuzhewuyou  
    OP
       2024-08-24 21:45:36 +08:00 via Android
    @yangxin0 我这也不是粘啊,大包分成快了吧,后面的包取不到
    julyclyde
        3
    julyclyde  
       2024-08-24 22:22:07 +08:00
    @wuzhewuyou 后面的可能就还没来
    或者说还没过内核协议栈

    要过了之后才能在应用层取到
    laminux29
        4
    laminux29  
       2024-08-25 00:16:34 +08:00
    先发送数据长度,再发送数据本体,就不会粘包了,建议有时间还是看看<<通信原理>>。

    或者干脆直接用通信框架,比如 gRPC ,这样你就不需要学 tcp 也不需要学通信原理,直接用 RPC 框架帮助你发送数据就行。
    victorc
        5
    victorc  
       2024-08-25 00:34:38 +08:00
    可以看一下 websocket 的协议,简单但是完备
    wuzhewuyou
        6
    wuzhewuyou  
    OP
       2024-08-25 06:41:56 +08:00 via Android
    @laminux29 数据包太大了,只能接收头部一部分
    p1gd0g
        7
    p1gd0g  
       2024-08-25 08:18:01 +08:00
    没遇到过这种情况。第一个长度是多少?不如直接贴个 demo ,大家好分析,本地 s2s 也不麻烦
    laminux29
        8
    laminux29  
       2024-08-25 09:31:22 +08:00
    @wuzhewuyou 你把完整的 Server 与 Client 端的代码发出来看看。
    Hhehepei
        9
    Hhehepei  
       2024-08-25 10:27:16 +08:00 via Android
    楼主可以参考一下标准库里 io.ReadAll()的实现
    securityCoding
        10
    securityCoding  
       2024-08-25 10:41:12 +08:00 via Android
    先找个二进制协议模版看一下先,比如 dubbo 那个协议图就画得很好
    Nazz
        11
    Nazz  
       2024-08-25 11:24:17 +08:00 via Android
    分段传输,写到文件里
    ilylx2008
        12
    ilylx2008  
       2024-08-25 11:33:39 +08:00
    发送的时候先发比如 4 字节长度值为 20000 ,后面发 20000 字节数据。
    读的时候,先读 4 字节,拿到长度 x ,再读后面 x 字节。
    wuzhewuyou
        13
    wuzhewuyou  
    OP
       2024-08-25 18:27:17 +08:00 via Android
    感谢,上了框架 go-netty ,问题解决,有空看看它是怎么实现的
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2699 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 09:55 · PVG 17:55 · LAX 02:55 · JFK 05:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.