使用bufio.NewReader(conn)读取整个消息。

huangapple go评论92阅读模式
英文:

Read whole message with bufio.NewReader(conn)

问题

我正在使用Go语言编写一个简单的聊天服务器和客户端。我在从net.Conn读取消息时遇到了一些问题。到目前为止,我一直在使用以下代码:

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

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

英文:

I am working on a simple chat server and client in golang. I am having some trouble with reading messages from the net.Conn. So far this is what I have been doing:

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

Since the user presses enter to send the message I only have to read until '\n'. But I am now working on encryption and when sending the public keys between client and server the key sometimes contains '\n', which makes it hard to get the whole key. I am just wondering how I can read the whole message instead of stopping at a specific character. Thanks!

答案1

得分: 8

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

// 创建长度前缀
prefix := make([]byte, 4)
binary.BigEndian.PutUint32(prefix, uint32(len(message)))

// 将前缀和数据写入流中(检查错误)
_, err := conn.Write(prefix)
_, err = conn.Write(message)

读取消息的方法如下:

// 读取长度前缀
prefix := make([]byte, 4)
_, err = io.ReadFull(conn, prefix)

length := binary.BigEndian.Uint32(prefix)
// 如果有限制,可以验证长度

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

参考链接:https://stackoverflow.com/questions/25766193/golang-tcp-client-server-data-delimiter/25766313#25766313

当然,你也可以使用现有的、经过充分测试的协议,如HTTP、IRC等,来满足你的消息传递需求。Go标准库提供了一个简单的textproto,或者你可以选择将消息封装在统一的编码格式中,如JSON。

英文:

A simple option for sending binary data is to use a length prefix. Encode the data size as a 32bit big endian integer, then read that amount of data.

// 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)

And to read the 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)

See also https://stackoverflow.com/questions/25766193/golang-tcp-client-server-data-delimiter/25766313#25766313

You can also of course use an existing, well test protocol, like HTTP, IRC, etc. for your messaging needs. The go std library comes with a simple textproto package, or you could opt to enclose the messages in a uniform encoding, like JSON.

huangapple
  • 本文由 发表于 2017年5月24日 21:28:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/44159811.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定