【问题标题】:Is there any way to send an array of Point with DataOutputStream over a Socket?有没有办法通过套接字发送带有 DataOutputStream 的 Point 数组?
【发布时间】:2012-06-20 22:22:26
【问题描述】:

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

【问题讨论】:

  • 只是为了确保它必须作为字节数组发送,还是我可以将它作为 Point 数组发送?
  • 这个问题令人困惑。您可以序列化 Point 数组并通过序列化(作为 ObjectOutputStream)发送。实际上,您可以通过 ByteArrayOutputStream 将 Point 数组序列化为字节数组,然后通过 DataOutputStream 发送字节数组,但必须单独发送每个字节。请准确说明您正在尝试做什么,以及您的限制的来源和细节。

标签: java arrays sockets datainputstream dataoutputstream


【解决方案1】:

参见例如Advanced Socket Programming 中的“传输自定义对象”部分:

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

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

【讨论】:

    【解决方案2】:

    为什么不改用 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;
    }
    }
    

    【讨论】:

      【解决方案3】:

      嗯,有几点你应该知道,例如,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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-05
        • 2013-01-16
        • 2022-06-24
        • 2017-09-28
        相关资源
        最近更新 更多