我想通过套接字发送一个带有 DataOutputStream 的点数组(点点[] = 新点[20]),并能够在另一端使用 DataInputStream 正确读取它。 我不能单独发送每个元素,它必须作为一个整体数组发送,并且能够被解释为一个完整的数组。
,请参阅高级套接字编程中的"传输自定义对象"部分:
- 将数据放入可序列化类,说我的数据。(在你的情况下,你真的不必这样做,因为数组实现了可序列化,但以后你可能会想要将其他数据与点数组一起发送......
- 在发送方,创建 MyData对象并用数据填充它。将socket.getOutputStream()转换为ObjectOutputStream,以及调用其 writeObject 方法来发送 MyData 对象。
- 在接收器上side,将socket.getInputStream()转换为ObjectInputStream,并调用它的 readObject 方法来接收对象(你必须强制转换它到我的数据)。
无论如何,我也会考虑使用RMI。例如,可以创建一个 PointServer,在 RMI 注册表中注册它,然后通过客户端应用程序中的简单函数调用来访问它。RMI 比套接字更容易使用。例如,您不必设计协议,只需为分布式对象定义方法。
为什么不使用 ObjectInputStream/ObjectOutputStream 呢?
这是我很久以前写的一段代码,它允许你通过网络发送任何类型的对象,只要它是可序列化的,很明显:
ObjectInputStream input = new ObjectInputStream(communicationSocket.getInputStream());
if (input != null) {
try {
Object o = input.readObject();
if (o != null && o instanceof DataObject) {
DataObject response = (DataObject) o;
{
//Do something cool with DataObject
}
}
}//etc...
DataObject
只是一个"包装器"/自定义类,您可以将其定义为具有 Point[] 的属性之一;换句话说,您可以将 DataObject 定义为:
import java.io.Serializable;
public class DataObject implements Serializable {
private Point[] points; //etc - define getter setter for points
}
你可以把它写成:
output = new ObjectOutputStream(communicationSocket
.getOutputStream());
output.writeObject(yourDataObject);
现在,您可以按如下方式阅读:
while (listening) {
try {
Object currentObject = input.readObject();
if (currentObject != null
&& currentObject instanceof DataObject) {
Point[] points = ((DataObject) currentObject).getPoints();
//Do something with points
}
}
catch (IOException e) {
e.printStackTrace();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
finally {
listening = false;
}
}
嗯,有一些要点你应该注意,例如,int 32 或 64 位的大小、发送和接收机器的字节顺序等。另外,应该有一个协议来通信两个套接字,我的意思是,每个数据包发送中都应该有一个标头,以便您知道要接收多少数据,我不会处理这个问题,我假设您想要发送和接收 20 点的数组。在此示例中,假设两台机器都是 32 位,即 int 的大小为 4 个字节,并且两台机器都使用字节顺序LITTLE_ENDIAN。
// To send an array of points use these two methods:
public byte[] pointsToBytes(Point[] p, int numPts)
{
// 2 is for x and y and 4 is the size of an int in bytes
ByteBuffer buff = ByteBuffer.allocateDirect(numPts * 2 * 4);
buff.order(ByteOrder.LITTLE_ENDIAN);
for (int i = 0; i < numPts; i++)
{
buff.putInt(p[i].x);
buff.putInt(p[i].y);
}
return buff.array();
}
public boolean sendData(Point[] pts, int size)
{
try
{
byte[] buffer = pointsToBytes(pts, size);
mainSocket.getOutputStream().write(buffer, 0, buffer.length);
return true;
}
catch (Exception e)
{
e.printStackTrace();
}
return false;
}
// To receive an array of point use these two methods:
public Point[] bytesToPoints(byte[] byteBuff, int numBytes)
{
ByteBuffer buff = ByteBuffer.wrap(byteBuff);
buff.order(ByteOrder.LITTLE_ENDIAN);
// 2 is for x and y and 4 is the size of an int in bytes
int ptsInBuffer = numBytes / 2 / 4;
Point[] pts = new Point[ptsInBuffer];
for (int i = 0; i < ptsInBuffer; i++)
{
pts[i].x=buff.getInt();
pts[i].y=buff.getInt();
}
return pts;
}
public Point[] getData(int pointsToRead)
{
try
{
byte[] buffer = new byte[pointsToRead * 4 * 2];
int bytesRead = mainSocket.getInputStream().read(buffer, 0, pointsToRead*4*2);
return bytesToPoints(buffer, bytesRead);
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}