我有两个小程序通过套接字很好地通信,其中接收方在Go中。当我的消息足够小以适应1024字节缓冲区并且可以从连接中的单个读取接收但现在我想从100k +或更多的图像传输数据时,一切都工作得很好。我假设正确的解决方案是不增加缓冲区,直到任何图像都适合内部。
伪转到:
var buf = make([]byte,1024)
conn, err := net.Dial("tcp", ":1234")
for {
r, err := conn.Read(buf[0:])
go readHandler(string(buf[0:r]),conn)
}
如何改进套接字读取例程以接受几个字节的简单消息以及更大的数据?如果您可以将总图像数据转换为io.Reader以在image.Decode中使用,则可获得奖励。
答案 0 :(得分:3)
我在Go中没有使用TCP的直接经验,但对我而言,您似乎成为了一个典型的误解TCP TCP提供的内容的受害者。
与UDP和SCTP形成鲜明对比的是,TCP没有消息边界的概念,因为它是面向流的。这意味着,TCP传输不透明的字节流,并且您几乎无法控制与接收方相关的流的“分块”。
我怀疑你所发现的“发送100k +消息”是发送方的运行时/网络库通常会“欺骗”你的内容缓冲区消耗你的“消息”然后在任何块的OS的TCP堆栈中流式传输它允许它(在无处不在的硬件/软件上通常约为8k)。接收器获取该流的大小完全未定义;唯一定义的是流中 bytes 的排序,这是保留的。
因此,您可能需要重新接受接收数据的方法。具体方法取决于流式传输数据的性质:
答案 1 :(得分:2)
您可以使用io.ReadFull
来阅读特定长度的[]byte
。这假设您事先知道需要读取多少字节。
对于image.Decode
,应该可以将conn
直接传递给image.Decode
函数。这假设您在解码图像之前不会从连接执行任何读取。
您的代码
for {
r, err := conn.Read(buf[0:])
go readHandler(string(buf[0:r]),conn)
}
似乎暗示你正在开始的goroutine是从conn
读取这似乎不是一个好主意,因为你最终会从连接中读取多个并发 (无法控制读取的顺序):for循环中的一个,readHandler
中的另一个。