我在GO中创建一个TCP服务器端,它接收TCP数据包并相应地发送响应。我能够监听连接,但是当客户端将TCP数据包发送到服务器时,服务器仅在重置连接时接收它们(TCP RST)。
这意味着当客户端发送数据包时,服务器会等待下一个数据包对第一个数据包执行某些操作。这是影响这部分问题的代码:
listener, err := net.Listen("tcp", ":25565")
if err != nil {
fmt.Println(err)
}
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println(err)
}
message, _ := ioutil.ReadAll(conn) // Get the bytes from the TCP packet
fmt.Println("Received connection " + conn.RemoteAddr().String())
HandlePacket(conn, message) // Do stuff with the data
conn.Close() // End the connection
}
HandlePacket(...)
解析数据包中收到的字节。问题是,当客户端发送第一个数据包时它什么都没有收到,然后在发送第二个数据包时打印出第一个数据包的数据。
答案 0 :(得分:4)
你的电话中有一个很大的提示就是从套接字中读取:
message, _ := ioutil.ReadAll(conn) // Get the bytes from the TCP packet
ReadAll()
不会只返回套接字缓冲区中的可用数据。 ReadAll()
将会读取,直到不再有任何数据要读取为止 - 直到流关闭。只有在连接关闭时,流才会关闭,如您所见。
您必须要求TCP套接字读取一些有限数量的数据。由于TCP不保留消息边界,因此您必须使用自己的成帧方案来了解要读取的数据量。
一个这样简单的方案就是让你的数据包始终是一些固定的大小。这可能很有用,例如,如果您正在为游戏的网络代码发送流式更新;只需将每个数据包写入256个字节,然后填入多达256个字节的位置更新;如果还有更多,只需发送更多数据包。
如果使用固定大小的帧不适合您,请考虑使用带有小标题的数据包。也许前4个字节是一个整数,告诉你消息有多长,然后是消息。然后,每次要读取数据包时,执行4个字节的硬读取以查找大小,然后从套接字读取多个字节。