【问题标题】:How to get rid of the empty remaining of the buffer?如何摆脱缓冲区的剩余空间?
【发布时间】:2012-01-03 23:17:14
【问题描述】:

我有一个使用数据报套接字交换消息的服务器-客户端应用程序。我最初将缓冲区大小设置为 1024 字节,因为我不知道消息的长度。当我发送小于 1024 字节的内容时,我的字符串的其余部分显示为一些奇怪的字符(空字符或者我不确定它们是如何被调用的)。 这是一个屏幕:

客户端代码: byte[] buf = ("This is another packet.\n").getBytes(); DatagramPacket packet = new DatagramPacket(buf, buf.length, inetAddress, serverport); socket.send(packet)

服务器代码: byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, buf.length); socket.receive(packet);

【问题讨论】:

  • 你说的是BufferedReader的大小还是别的什么?
  • IMO,最好更新您的 OP,而不是在 cmets 中发布您的代码。
  • @MikeMokkas UDP 数据报的最大大小为 65k。 short 给出的范围是 0 到 32 767(仅仅是因为您不能有负数据大小),并且我们没有任何大于 32767 的消息。如果有,则附加一个 4 字节整数。这仍然会为您留下 64k - 4 字节的可用数据传输空间。
  • @ThomasOwens,您可以使用 char 作为无符号 16 位值。
  • @Thomas:你在这里混淆了很多零碎的东西。首先也是最重要的是Java DatagramPackets 知道它们的长度,因此绝对不需要在数据包的有效负载中对​​其进行编码。除此之外,没有理由考虑 Java 数据类型的“签名性”来决定是否需要 2 个字节(最多 64kB)或 4 个字节(最多 4TB)来编码数据包长度。最后,UDP数据报的最大载荷长度(Java DatagramSocket BTW不限于UDP)既不是65也不是64kB,而是受到IP数据包长度限制。

标签: java sockets networking udp datagram


【解决方案1】:
socket.receive(packet);
byte[] data = new byte[packet.getLength()];
System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength());

【讨论】:

    【解决方案2】:

    DatagramPacket.getLength() 返回接收到的数据包的实际长度。除非您使用非零偏移量创建数据包,否则这意味着数据位于 {0..getLength()-1}

    请注意,这意味着您创建 DatagramPacket 的原始长度丢失了,这反过来意味着您必须在每次接收时使用新的 DatagramPacket,或者至少通过 setData() 重新初始化其数据缓冲区.否则DatagramPacket 将继续缩小到收到的最小数据包的大小。

    【讨论】:

      【解决方案3】:

      您必须检查packet.getOffset() 以查找缓冲区中接收数据的开始位置,并检查packet.getLength() 以获取数据的长度(以字节为单位)。

      您还应该考虑,如果接收到的数据包太大而无法放入提供的缓冲区(在您的情况下 >1024 字节),则只会丢弃额外的数据。除非您必须非常小心内存使用,否则您应该使用更大的缓冲区以确保整个数据包都适合。对于 UDP,最大数据包大小为 64kB。

      【讨论】:

      • 我知道它从哪里开始,它总是从第一个字节开始,但我不知道我的字符串 在哪个字节结束,然后那些空字符开始出现。
      【解决方案4】:

      好的,所以我想出了一个适合我的解决方案:

          public String getRidOfAnnoyingChar(DatagramPacket packet){
              String result = new String(packet.getData());
              char[] annoyingchar = new char[1];
              char[] charresult = result.toCharArray();
              result = "";
              for(int i=0;i<charresult.length;i++){
                  if(charresult[i]==annoyingchar[0]){
                      break;
                  }
                  result+=charresult[i];
              }
              return result;
          }
      

      编辑: 使用ByteArrayOutputStream 存在更好的解决方案,可以在这里找到:How to reinitialize the buffer of a packet?

      【讨论】:

      • 太可怕了。可怕。正确的解决方案就是return new String(packet.getData(), packet.getOffset(), packet.getLength()); Downvote。
      • 毛总毛数
      猜你喜欢
      • 1970-01-01
      • 2019-08-21
      • 2011-08-21
      • 2012-10-24
      • 1970-01-01
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多