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

wuzhewuyou · 2024-8-24 21:21:39 · 98 次点击
如题,据说论坛日经月经都是 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 一直循环中,读取不到更多数据


求解?数据哪里去了,怎样能取出?
举报· 98 次点击
登录 注册 站外分享
9 条回复  
yangxin0 小成 2024-8-24 21:26:59
如果还停留在“粘包”这个概念,就该回去复习 computer network & TCP/IP 了,TCP 的抽象是 stream 也就是流,站在使用者的界面来看一定是流的 API 。
julyclyde 小成 2024-8-24 22:22:07
@wuzhewuyou 后面的可能就还没来
或者说还没过内核协议栈

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

或者干脆直接用通信框架,比如 gRPC ,这样你就不需要学 tcp 也不需要学通信原理,直接用 RPC 框架帮助你发送数据就行。
victorc 小成 2024-8-25 00:34:38
可以看一下 websocket 的协议,简单但是完备
p1gd0g 小成 2024-8-25 08:18:01
没遇到过这种情况。第一个长度是多少?不如直接贴个 demo ,大家好分析,本地 s2s 也不麻烦
Hhehepei 小成 2024-8-25 10:27:16
楼主可以参考一下标准库里 io.ReadAll()的实现
securityCoding 初学 2024-8-25 10:41:12
先找个二进制协议模版看一下先,比如 dubbo 那个协议图就画得很好
Nazz 小成 2024-8-25 11:24:17
分段传输,写到文件里
ilylx2008 小成 2024-8-25 11:33:39
发送的时候先发比如 4 字节长度值为 20000 ,后面发 20000 字节数据。
读的时候,先读 4 字节,拿到长度 x ,再读后面 x 字节。
返回顶部