0

我想通过套接字发送带有 DataOutputStream 的点数组(Point points[] = new point[20]),并能够在另一端使用 DataInputStream 正确读取它。我不能单独发送每个元素,它必须作为整个数组发送并且能够被解释为整个数组。

4

3 回答 3

1

请参阅高级套接字编程中的“传输自定义对象”部分:

  1. 将您的数据放入Serializable 类中,例如 MyData。(在您的情况下,您实际上不必这样做,因为数组实现了可序列化,但是稍后您可能希望将其他数据与您的点数组一起发送......)
  2. 发送方,创建一个 MyData 对象并用数据填充它。将 socket.getOutputStream() 转换为ObjectOutputStream,并调用其writeObject方法发送 MyData 对象。
  3. 接收 方,将 socket.getInputStream() 转换为ObjectInputStream,并调用其readObject方法来接收对象(您必须将其转换为 MyData)。

无论如何,我也会考虑使用RMI。例如,您可以创建一个 PointServer,在 RMI 注册表中注册它,然后通过客户端应用程序中的简单函数调用来访问它。RMI 比套接字更容易使用。例如,您不必设计协议,只需为您的分布式对象定义方法。

于 2012-06-20T22:51:21.513 回答
0

为什么不使用 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;
}
}
于 2012-06-20T23:29:58.510 回答
0

嗯,有一些你应该注意的点,例如,32 位或 64 位 int 的大小,发送和接收机器的字节顺序等。另外,应该有一个协议来通信两个套接字,我的意思是,在每个发送的数据包中都应该有一个标头,以便您知道要接收多少数据,我不会处理这个问题,我假设您要发送和接收 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;
}
于 2013-04-19T11:04:53.467 回答