gpt4 book ai didi

java - 截断 DatagramPacket 字节数组

转载 作者:行者123 更新时间:2023-12-01 12:35:47 28 4
gpt4 key购买 nike

我正在使用 DatagramPacketDatagramSocket 来创建客户端/服务器情况。我有一个带有简单客户端和服务器的工作项目。客户端将向服务器发送一个序列化对象,仅此而已。

下面显示的代码完美运行。我将发布整个类,以便万一有人想运行代码,这应该是可能的。

我想做的是将发送的数据截断为刚好适合的数组(基于 How to get rid of the empty remaining of the buffer? )。

当我打印出发送的长度和收到的长度时,我得到以下输出:

GameClient: sent 330 bytes to the server
GameServer: received 330 bytes

我在接收端首先做的是:

        socket.receive(packet);
// Deserialize the object.
TestObject received = TestObject.deserialize(packet.getData());

但是,我已将缓冲区大小设置为任意大小,因此我认为应该将实际字节放入适合该对象的字节数组中。所以我尝试了以下方法:

        socket.receive(packet);
// Truncate the data into a smaller byte array.
int actualSize = packet.getLength();
byte[] actualPacket = new byte[actualSize];
System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength());

// Deserialize the object.
TestObject received = TestObject.deserialize(actualPacket); // Does not work.

但是,这段代码给了我期望

java.io.StreamCorruptedException: invalid stream header: 00000000

在第一行 TestObjectdeserialize 方法中抛出:

        ObjectInputStream iStream = new ObjectInputStream(
new ByteArrayInputStream(data));

这里可能出现什么问题?数据是精确的副本,对吧?

发送对象

package net;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class TestObject implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 1L;
public int value;
public double anotherValue;
public byte[] fillMe;

public TestObject(int value)
{
super();
this.value = value;
fillMe = new byte[123];
}

public TestObject(int value, double anotherValue)
{
super();
this.value = value;
this.anotherValue = anotherValue;
}

public static byte[] serialize(TestObject o)
{
try
{
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
// get the byte array of the object
byte[] obj = baos.toByteArray();
baos.close();
return obj;
} catch (Exception e)
{
e.printStackTrace();
}

return null;
}

public static TestObject deserialize(byte[] data)
{
try
{
ObjectInputStream iStream = new ObjectInputStream(
new ByteArrayInputStream(data));
TestObject obj = (TestObject) iStream.readObject();
iStream.close();
return obj;
} catch (Exception e)
{
e.printStackTrace();
}

return null;
}
}

SERVER(接收端)

package net;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

import utils.Printer;
import engine.board.GameBoard;

public class GameServer extends Thread
{ private static int BUFFER_SIZE = 64000; //64k buffer
private static final int SERVER_LISTENING_PORT = 1234;
private DatagramSocket socket;
private GameBoard game;

public GameServer(GameBoard game)
{
this.game = game;
try
{
this.socket = new DatagramSocket(SERVER_LISTENING_PORT);
} catch (SocketException e)
{
e.printStackTrace();
}
}

public void run()
{
while(true)
{
byte[] data = new byte[BUFFER_SIZE];
DatagramPacket packet = new DatagramPacket(data, data.length);
try
{
socket.receive(packet);
Printer.debugMessage(this.getClass(), String.format("received %s bytes", packet.getLength()));
} catch (IOException e)
{
e.printStackTrace();
}
// Truncate the data into a smaller byte array.
int actualSize = packet.getLength();
byte[] actualPacket = new byte[actualSize];
System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength());

// Deserialize the object.
TestObject received = TestObject.deserialize(actualPacket); // Does not work.
//TestObject received = TestObject.deserialize(packet.getData()); // Works fine?
System.out.println("Server received object with value " + received.value);
}
}
}

客户端(发送端)

package net;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import utils.Printer;
import engine.board.GameBoard;

public class GameClient
{
private static int BUFFER_SIZE = 64000;
private static final int SERVER_LISTENING_PORT = 1234;
private InetAddress serverIp;
private DatagramSocket socket;
private GameBoard game;
private String clientName;

public GameClient(String name, GameBoard game, String ipAddress)
{
this.game = game;
this.clientName = name;
try
{
this.socket = new DatagramSocket();
this.serverIp = InetAddress.getByName(ipAddress);
} catch (SocketException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnknownHostException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}


public void sendData(byte[] data)
{
DatagramPacket packet = new DatagramPacket(data, data.length, serverIp, SERVER_LISTENING_PORT);

try
{
socket.send(packet);
Printer.debugMessage(this.getClass(), String.format("sent %d bytes to the server", data.length));;

} catch (IOException e)
{
e.printStackTrace();
}
}
}

测试代码

import net.GameClient;
import net.GameServer;
import net.TestObject;


public class Scratchpad
{
static GameServer server;
static GameClient client;
static GameClient client2;
public static void main(String[] args)
{
// Start the server
server = new GameServer(null);
server.start();

// Init client (sender).
client = new GameClient("client1", null, "localhost");

// Create object to send.
TestObject tester = new TestObject(1234);

// Send the object.
client.sendData(TestObject.serialize(tester));
//client2.sendData("hello world".getBytes());
}
}

最佳答案

你不需要这些。您只需从原始 byte[] 数组反序列化即可。它将停在对象的末尾。最后的任何尾随内容都会被忽略。

但是,您可以大大简化新代码:

    TestObject received = TestObject.deserialize(packet.getData(), packet.getOffset(), packet.getLength());

并将反序列化方法更改为:

public static TestObject deserialize(byte[] data, int offset, int length)
{
try
{
ObjectInputStream iStream = new ObjectInputStream(
new ByteArrayInputStream(data, offset, length));
// etc ...
}

我会进一步修改它以允许它抛出异常而不是默默地吞掉它们。返回 null 是一个特别糟糕的策略,因为 null 是一个带内值,可能是您尝试传输的值。

关于java - 截断 DatagramPacket 字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25611248/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com