为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
潇潇雨雨 2021-12-20 11:00:25
我正在 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 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

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

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

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

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

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

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


查看完整回答
反对 回复 2021-12-20
  • 1 回答
  • 0 关注
  • 294 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号