当前位置:  开发笔记 > 编程语言 > 正文

如何重新初始化数据包的缓冲区?

如何解决《如何重新初始化数据包的缓冲区?》经验,为你挑选了1个好方法。

当我从netcat或我的客户端向我的UDP服务器发送UDP数据包时,我遇到了一些问题,该服务器监听广播UDP数据包.问题是我无法重新启动And的缓冲区socket.receive(packet);当你检查我的控制台输出时,你会看到数据包被发送或接收两次甚至更多次,最烦人的是当我发送一个更长的数据包时,下一个较小的一部分是前一部分!(控制台输出上的HERE标记了问题)我的客户端和服务器位于同一LAN上.

客户代码:

DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
byte[] buf = ("Hello from Client").getBytes();
byte[] buf2 = ("omg").getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, getBroadcastAddress(UDPConnection.context), Server.SERVERPORT);
DatagramPacket packet2 = new DatagramPacket(buf2, buf2.length, getBroadcastAddress(UDPConnection.context), Server.SERVERPORT);
Log.d("UDP", "C: Sending: '" + new String(buf) + "'");
socket.send(packet);
socket.send(packet2);

服务器代码:

void run(){
MulticastSocket socket = new MulticastSocket(SERVERPORT);
socket.setBroadcast(true);
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
while(true){
    Log.d("UDP", "S: Receiving...");
    socket.receive(packet);
    //socket.setReceiveBufferSize(buf.length);
    packet.setData(buf);
    Log.i("BUFFER_packet",packet.getLength()+"");
    Log.i("BUFFER_socket",socket.getReceiveBufferSize()+"");
    Log.d("UDP", "S: From: " + packet.getAddress().getHostAddress());
    Log.d("UDP", "S: Received: "+getRidOfAnnoyingChar(packet));
    Log.d("UDP", "S: Done.");
}
}
    //this method is getting rid of the "questionmark in a black diamond" character
    public String getRidOfAnnoyingChar(DatagramPacket packet){
        Log.i("UDP","Inside getridofannoyingchar method.");
        String result = new String(packet.getData());
        char[] annoyingchar = new char[1];
        char[] charresult = result.toCharArray();
        result = "";
        for(int i=0;i

安慰:

11-27 18:15:27.515: D/UDP(15242): S: Connecting...
11-27 18:15:27.519: I/ServerIP(15242): ::
11-27 18:15:27.519: I/LocalIP(15242): 192.168.0.4
11-27 18:15:27.523: D/UDP(15242): S: Receiving...
11-27 18:15:28.031: D/UDP(15242): C: Connecting...
11-27 18:15:28.039: I/BroadcastIP(15242): 192.168.0.255
11-27 18:15:28.042: I/BroadcastIP(15242): 192.168.0.255
11-27 18:15:28.070: D/UDP(15242): C: Sending: 'Hello from Client'
11-27 18:15:28.074: I/BUFFER_packet(15242): 1024
11-27 18:15:28.074: I/BUFFER_socket(15242): 110592
11-27 18:15:28.074: D/UDP(15242): S: From: 192.168.0.4
11-27 18:15:28.074: I/UDP(15242): Inside getridofannoyingchar method.
11-27 18:15:28.078: I/BUFFER_packet(15242): 1024
11-27 18:15:28.078: I/BUFFER_socket(15242): 110592
11-27 18:15:28.078: D/UDP(15242): S: From: 192.168.0.4
11-27 18:15:28.078: I/UDP(15242): Inside getridofannoyingchar method.
11-27 18:15:28.085: D/UDP(15242): S: Received: Hello from Client <------------HERE
11-27 18:15:28.085: D/UDP(15242): S: Done.
11-27 18:15:28.085: D/UDP(15242): S: Receiving...
11-27 18:15:28.085: D/UDP(15242): S: Received: Hello from Client <------------HERE
11-27 18:15:28.085: D/UDP(15242): S: Done.
11-27 18:15:28.085: D/UDP(15242): S: Receiving...
11-27 18:15:28.085: I/BUFFER_packet(15242): 1024
11-27 18:15:28.085: I/BUFFER_socket(15242): 110592
11-27 18:15:28.085: D/UDP(15242): S: From: 192.168.0.4
11-27 18:15:28.085: I/UDP(15242): Inside getridofannoyingchar method.
11-27 18:15:28.089: D/UDP(15242): S: Received: omglo from Client <------------HERE
11-27 18:15:28.089: D/UDP(15242): S: Done.
11-27 18:15:28.089: D/UDP(15242): S: Receiving...
11-27 18:15:28.089: I/BUFFER_packet(15242): 1024
11-27 18:15:28.089: I/BUFFER_socket(15242): 110592
11-27 18:15:28.089: D/UDP(15242): S: From: 192.168.0.4
11-27 18:15:28.089: I/UDP(15242): Inside getridofannoyingchar method.
11-27 18:15:28.089: D/UDP(15242): S: Received: omglo from Client <------------HERE
11-27 18:15:28.089: D/UDP(15242): S: Done.
11-27 18:15:28.089: D/UDP(15242): S: Receiving...
11-27 18:15:28.089: D/UDP(15242): C: Sent.
11-27 18:15:28.089: D/UDP(15242): C: Done.

任何帮助将非常感谢!:)

PS.控制台中可能有一些输出,例如Done/Sent/Connecting/Receiving,但未添加到我的示例代码中,但所有Received:/ BUFFER_packet/_socket/From都存在.



1> AntonyM..:

你不需要重新初始化数据包中的缓冲区,你只需要将缓冲区的内容重置为最初的任何内容(即你需要用零填充接收数组).

致电:

Arrays.fill(BUF,(字节)0);

在服务器端将数组重置为零,因为Java中的数组是按引用传递而不是按值传递(即,您对数组内容的引用与DatagramPacket具有的引用相同,因此您可以无需经过DatagramPacket方法即可修改它.

已经说过你对数据进行序列化/反序列化的方式并不理想.你最好使用ByteArrayOutputStream和ByteArrayInputStream包裹发送和接收缓冲区,然后使用DataOutputStream/DataInputStream.这些将允许您以明确定义的格式写入和读取字符串,这可能存储字符串的长度,以便无论如何都会忽略缓冲区上的任何剩余数据.以这种方式正确地序列化/反序列化也将消除剥离"黑钻石"字符的需要.

DataOutputStream.writeUTF

如果你对这背后的原因感兴趣,那就是使用java.lang.String的默认序列化(getBytes()和new String(byte []))以及如何填充UDP数据包.我会尝试把它归结为关键点:

Java的String对象的内部表示不是字节数组 - 它是一个char数组.Java的字符是不一样的字节 - 一个字符实际上是2个字节,因为它需要能够代表的不仅仅是拉丁字母以上(ACBD ......),它需要支持从像的东西其他语言/文化其它字符西里尔文,汉字等和一个字节是不够的(一个字节可以获得256种可能性,2个字节可以获得65536种可能性).

因此,当您调用getBytes()时,Java必须使用一些"scheme"(编码)将该字符数组转换为字节数组(序列化).个中详情没有太大的关系,但是当你发送字节的第一个块,(可以说其10个字节长)你读了包成一个更大的缓冲区(1024个字节).然后,您要求Java String对整个缓冲区进行反序列化,而不仅仅是10个字节.

该方案(编码)不知道,只与前10个字节处理,因此试图将整个1024个字节进行解码,然后你在你的字符串,如黑钻,或(如你已经把其他一些变得怪异字符通过发送'hello'在10个字节之后的数据,你将前一个接收的字符混合到你的字符串中.

使用写/的readUTF将写入字节数组,以及数据的长度,所以当你读一遍就知道它只有读取前10个字符(或然而,许多是有效的).

推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有