在端口上侦听TCP数据包仅在连接关闭时读取数据

时间:2016-03-03 03:47:48

标签: go

我在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(...)解析数据包中收到的字节。问题是,当客户端发送第一个数据包时它什么都没有收到,然后在发送第二个数据包时打印出第一个数据包的数据。

1 个答案:

答案 0 :(得分:4)

你的电话中有一个很大的提示就是从套接字中读取:

message, _ := ioutil.ReadAll(conn) // Get the bytes from the TCP packet

ReadAll()不会只返回套接字缓冲区中的可用数据。 ReadAll()将会读取,直到不再有任何数据要读取为止 - 直到流关闭。只有在连接关闭时,流才会关闭,如您所见。

您必须要求TCP套接字读取一些有限数量的数据。由于TCP不保留消息边界,因此您必须使用自己的成帧方案来了解要读取的数据量。

一个这样简单的方案就是让你的数据包始终是一些固定的大小。这可能很有用,例如,如果您正在为游戏的网络代码发送流式更新;只需将每个数据包写入256个字节,然后填入多达256个字节的位置更新;如果还有更多,只需发送更多数据包。

如果使用固定大小的帧不适合您,请考虑使用带有小标题的数据包。也许前4个字节是一个整数,告诉你消息有多长,然后是消息。然后,每次要读取数据包时,执行4个字节的硬读取以查找大小,然后从套接字读取多个字节。