【问题标题】:Listening for TCP packets on port only reads data when connection closes侦听端口上的 TCP 数据包仅在连接关闭时读取数据
【发布时间】:2016-03-03 12:10:38
【问题描述】:

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

【问题讨论】:

    标签: go


    【解决方案1】:

    重要的提示就在您从套接字读取的调用中:

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

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

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

    这样一个简单的方案是使您的数据包始终具有固定大小。这可能很有用,例如,如果您正在为游戏的网络代码发送流式更新;只需将每个数据包设为 256 字节,并在 256 字节中填充尽可能多的位置更新;如果有更多,只需发送更多数据包。

    如果使用固定大小的帧不适合您,请考虑使用带有小标头的数据包。也许前 4 个字节是一个整数,告诉您消息有多长,然后是消息。然后,每次你想读一个数据包时,你硬读 4 个字节来找出它的大小,然后从套接字中读取那么多字节。

    【讨论】:

    • 谢谢,这看起来确实不错。但是,函数 Read() int 返回值代表什么? (如,Read(b []byte) (n int, err error))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    • 1970-01-01
    • 2021-02-26
    相关资源
    最近更新 更多