【发布时间】:2018-11-19 19:00:26
【问题描述】:
我有一个 tcp 服务器和一个客户端,服务器执行以下操作
func providerCallback(conn net.Conn) {
reader := bufio.NewReader(conn)
var err error
for {
lenbyte, _ := reader.Peek(4)
reader.Discard(4)
slen := int(binary.BigEndian.Uint32(lenbyte))
data, err = reader.Peek(slen)
process(data)
reader.Discard(slen)
}
}
客户端发送数据包的速度似乎比进程可以处理的快,因此我想在 bufio 中缓冲请求并稍后处理。
但是,由于bufio的大小是固定的(4096,虽然我可以增加,但还是固定的),这意味着我不能手动Reset它,因为最后可能会有一个数据包切割bufio的,如下
|普通数据... [数据包 P 的前 20 个字节] | [包P的其余部分]
|------------------- bufio 的大小 ------------------|
如何拼接被切断的数据包,并将 bufio 重新用于以后的数据包?
【问题讨论】:
-
如果服务器读取数据的速度不如客户端发送数据的速度,那么 TCP 的流控会自动减慢客户端的速度。无需在您的应用程序中执行此操作。
-
谢谢,但这似乎是操作系统级别或网络堆栈级别。当客户端自动变慢时,已经有很多数据包发送到服务器。我认为服务器仍然需要处理被分成 2 块的数据包。
-
没有所谓的“切成2块”。 TCP 是字节流协议,而不是基于消息的协议。您不应该对数据包大小等做出任何假设,也不应该假设发送方的单次写入会导致接收方的单次读取。如果您需要消息语法,那么您需要将其添加到您的应用程序协议中,即消息以长度为前缀,有明确的消息分隔符或类似内容。
-
@SteffenUllrich 我想我没有在文本描述中说清楚,但我确实在代码中使用了“4 字节长度 + 内容”应用程序协议。无论如何,彼得的回答对我来说看起来不错,我会将这个问题标记为已解决。感谢您的评论。
标签: sockets go networking tcp network-programming