当前位置: 首页 > 知识库问答 >
问题:

Golang中的TCP固定大小报文成帧方法

闻人伟
2023-03-14

我不能理解如何使用固定大小的前缀长度头的消息帧工作。

据说固定大小的字节数组将包含要发送的消息的长度。但是如何定义固定大小的字节数组,特别是在Golang中。

Hello
5:Hello // [53 58 104 101 108 108 111]
36:Hello, this is just a dumb question. // [51 54 58 72 101 108 108 111 44 32 116 104 105 115 32 105 115 32 106 117 115 116 32 97 32 100 117 109 98 32 113 117 101 115 116 105 111 110 46]

因此这里的36需要2个字节。

我想到的一种方法是考虑协议的最大消息长度。假设10KB=10240字节。然后将前导0添加到消息长度。这样,我肯定我将有一个固定的5字节的头。

这对所有的案子都管用吗?

golang prettyprint-override">    const maxLengthBytes = 8
    conn, err := net.Dial("tcp", "127.0.0.1:9999")
    if err != nil {
        fmt.Println(err)
        return
    }
    message := "Hello, this is just a dumb question"
    bs := make([]byte, maxLengthBytes)
    binary.LittleEndian.PutUint64(bs, uint64(len(text)))
    bytes := append(bs, []byte(text)...)
    conn.Write(bytes)

服务器:

    listener, err := net.ListenTCP("tcp", &net.TCPAddr{Port: 9999})
    if err != nil {
        fmt.Println(err)
        return
    }
    for {
        tcp, err := listener.AcceptTCP()
        if err != nil {
            fmt.Println(err)
            continue
        }
        go Reader(tcp)
    }

func Reader(conn *net.TCPConn) {
    foundLength := false
    messageLength := 0
    for {
        if !foundLength {
            var b = make([]byte, maxLengthBytes)
            read, err := conn.Read(b)
            if err != nil {
                fmt.Println(err)
                continue
            }
            if read != 8 {
                fmt.Println("invalid header")
                continue
            }
            foundLength = true
            messageLength = int(binary.LittleEndian.Uint64(b))
        } else {
            var message = make([]byte, messageLength)
            read, err := conn.Read(message)
            if err != nil {
                fmt.Println(err)
                continue
            }
            if read != messageLength {
                fmt.Println("invalid data")
                continue
            }
            fmt.Println("Received:", string(message))
            foundLength = false
            messageLength = 0
        }
    }
}

共有1个答案

卢皓轩
2023-03-14

请参考我在这篇文章中的回答TCP客户端for Android:文本未完整接收

基本上,您必须定义如何存储/格式化数据。例如:

>

  • 我们将前缀长度存储为int32(4个字节),并使用少量的endian。和你的不一样。

    我们有很多方法来处理长度限制,如果它是我们所关心的(实际上,几乎应用程序协议都有它的最大请求大小)。您可以多用一个位来指示消息是否超过最大长度来解析它,对吗?

  •  类似资料:
    • 获取下面的错误,当尝试cmd as: 我已经运行了cmd来运行测试并正确生成csv文件 我也试过这个,但没用。 使用Jmeter 5.4.3,通过brew安装 java-v:

    • 问题 你想在一个固定长度记录或者数据块的集合上迭代,而不是在一个文件中一行一行的迭代。 解决方案 通过下面这个小技巧使用 iter 和 functools.partial() 函数: from functools import partial RECORD_SIZE = 32 with open('somefile.data', 'rb') as f: records = iter(p

    • 问题内容: 我想用Java创建一个Stack,但是要固定大小。例如,创建一个新的堆栈,将大小设置为10,然后在将项目推入堆栈时将其填满,并在将其填满到十时将堆栈中的最后一个项目推出(移出)。我想使用Stack,因为它使用LIFO,非常适合我的需求。 但是Stack从Vector继承的setSize()方法似乎并没有真正限制Stack的大小。我想我缺少有关堆栈如何工作的信息,或者堆栈并不是要受到约束

    • 将Blockly放入网页的最简单方法是将其注入空的“div”标签。 注入 首先,包括核心Blockly脚本和核心模块。请注意,路径可能会有所不同,具体取决于您的网页与Blockly文件相关的位置: <script src="blockly_compressed.js"></script> <script src="blocks_compressed.js"></script> 然后包含用户语言的消

    • 问题内容: 以下代码是我编写的PHP Web服务的一部分。它需要一些上载的Base64数据,对其进行解码,然后将其附加到文件中。这一切都很好。 问题是,当我在追加操作之后读取文件大小时,会得到文件在追加操作之前的大小。 我究竟做错了什么? 系统是: PHP 5.2.14 阿帕奇2.2.16 Linux内核2.6.18 问题答案: 在基于Linux的系统上,提取的数据是“ statcached”。

    • 本文向大家介绍将一个数组按照固定大小进行拆分成数组的方法,包括了将一个数组按照固定大小进行拆分成数组的方法的使用技巧和注意事项,需要的朋友参考一下 如下所示: 以上这篇将一个数组按照固定大小进行拆分成数组的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。