【问题标题】:Java NIO server how to read variable-len packets w/out any headerJava NIO服务器如何读取不带任何标头的可变长度数据包
【发布时间】:2013-08-27 22:14:50
【问题描述】:

为了好玩,我正在学习制作类似于 Bukkit 的 Minecraft 服务器。我以前和 NIO 打过交道,但不是很多,也不是很实用。我现在遇到一个问题,我的世界有许多可变长度的数据包,并且由于这些数据包没有任何一致的“标头”,NIO 正在做这个奇怪的事情,它将数据包分段,因为数据并不总是立即完整发送。

我最近从这个帖子中了解到这是一件事:Java: reading variable-size packets using NIO 我宁愿不使用 Netty/MINA/etc。因为我想自己学习这一切,因为我这样做是为了教育,而不是想把它变成一个巨大的项目。

所以我的问题是,我该如何防止这种数据包碎片化?我尝试在java.net.Socket#setTcpNoDelay(boolean on) 中使用 Nagle 的算法,但奇怪的是,所有这些都是为了使每次发送数据包时都会分段,而当我没有启用它时,第一个数据包总是通过 OK,然后后面的数据包就会变成碎片。

我非常密切地关注Rox Java NIO Tutorial,所以我知道这段代码应该可以工作,但该教程仅将字符串消息回显给对等方,而不是复杂的字节流。

这是我的代码。在某些情况下,我使用Executor#execute(Runnable) 创建两个线程。由于我仍在学习线程和并发性并尝试将它们与网络拼凑在一起,因此也非常感谢您对此的任何反馈!

ServerSocketManager ServerDataManager

非常感谢,我知道这是相当多的东西,所以我不能感谢你花时间阅读和回复!

【问题讨论】:

  • NIO 没有任何碎片。 TCP 就是这样做的。这是接收 TCP 流的正常行为。你必须相应地编码。
  • @EJP 所以...怎么样?对不起,如果它很笨,但我真的不知道该怎么做。

标签: java sockets nio


【解决方案1】:

TCP 总是一个字节流。您无法控制何时获得它们或获得多少。它可以随时以任何数量进入。这就是协议存在的原因。

标头是协议的常见部分,用于告诉您在获得完整消息之前需要读取多少数据。

所以这里的简短回答是:你不能。

你说你不想做的一切——这就是你必须做的。

【讨论】:

  • 这真的很不幸。有点奇怪 Mojang 是如何做到这一点的,而不是仅仅拥有一个一致的协议!现在我将不得不放弃我所做的所有工作并转向 Netty,这非常可悲,但我猜 Netty 看起来很酷。我开始认为这可能就是会发生的事情!还是谢谢你!
  • Netty 帮不上忙。你仍然需要循环。没有灵丹妙药。
  • @EJP 不,我知道这一点,但 Netty 具有类似 ReplayingDecoder 的功能,这让我更轻松。
  • LOL 我喜欢答案的结尾。 “你说你不想做的一切——这就是你必须做的。分享编辑关注标志”
  • @kimathie 不错的复制/粘贴工作:-P 分享编辑关注标志
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-26
  • 1970-01-01
  • 1970-01-01
  • 2019-04-15
  • 1970-01-01
相关资源
最近更新 更多