【问题标题】:Read whole message with bufio.NewReader(conn)使用 bufio.NewReader(conn) 阅读整条消息
【发布时间】:2017-05-24 22:21:10
【问题描述】:

我正在使用 golang 开发一个简单的聊天服务器和客户端。我在阅读来自 net.Conn 的消息时遇到了一些问题。到目前为止,这就是我一直在做的事情:

bufio.NewReader(conn).ReadString('\n')

由于用户按下回车键发送消息,我只需要阅读直到'\n'。但我现在正在研究加密,当在客户端和服务器之间发送公钥时,密钥有时包含'\n',这使得很难获得整个密钥。我只是想知道如何阅读整个消息而不是停留在特定字符处。谢谢!

【问题讨论】:

  • TCP 是一个面向流的协议,它没有“消息”。您需要一个不同的协议来构建您的消息。您可以简单地使用长度前缀、netstrings、bencode、HTTP,有很多选项。
  • @JimB 你能给我一个使用长度前缀的简单例子吗?这是我第一个使用 golang 的项目,我没有太多的网络经验。谢谢。
  • 除了框架问题,代码bufio.NewReader(conn).ReadString('\n') 将成为问题的根源,因为缓冲区被丢弃。为每个连接创建一次 bufio.Reader,而不是每次应用从连接中读取时创建一次。

标签: networking encryption go chat public-key-exchange


【解决方案1】:

发送二进制数据的一个简单选项是使用长度前缀。将数据大小编码为 32 位大端整数,然后读取该数据量。

// create the length prefix
prefix := make([]byte, 4)
binary.BigEndian.PutUint32(prefix, uint32(len(message)))

// write the prefix and the data to the stream (checking errors)
_, err := conn.Write(prefix)
_, err = conn.Write(message)

并阅读消息

// read the length prefix
prefix := make([]byte, 4)
_, err = io.ReadFull(conn, prefix)


length := binary.BigEndian.Uint32(prefix)
// verify length if there are restrictions

message = make([]byte, int(length))
_, err = io.ReadFull(conn, message)

另见Golang: TCP client/server data delimiter

当然,您也可以使用现有的良好测试协议,如 HTTP、IRC 等来满足您的消息传递需求。 go std 库带有一个简单的textproto package,或者您可以选择将消息包含在统一编码中,例如 JSON。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    相关资源
    最近更新 更多