简体   繁体   English

有什么方法可以通过Socket发送带有DataOutputStream的Point数组吗?

[英]Is there any way to send an array of Point with DataOutputStream over a Socket?

I want to send an array of point (Point points[] = new point[20]) with DataOutputStream over a socket and be able to correctly read it with DataInputStream on the other side. 我想通过套接字通过DataOutputStream发送一个点数组(Point points [] = new point [20]),并能够在另一侧使用DataInputStream正确读取它。 I CANNOT send each element separately, it must be sent as a whole array and be able to be interpreted as a whole array. 我不能单独发送每个元素,它必须作为一个整体数组发送,并且能够被解释为一个整体数组。

See eg the section "Transporting Custom Objects" in Advanced Socket Programming : 请参见“ 高级套接字编程 ”中的“传输自定义对象”部分:

  1. Put your data into a Serializable class , say MyData. 将您的数据放入Serializable类 ,例如MyData。 (You don't really have to do this in your case, because arrays implement Serializable, but there is a chance that later you will want to send other data along with your point array...) (由于数组实现了Serializable,因此您实际上不必这样做,但是以后您可能会希望将其他数据与点数组一起发送...)
  2. On the sender side, create a MyData object and fill it with data. 发送方,创建一个MyData对象,并用数据填充它。 Cast socket.getOutputStream() to an ObjectOutputStream , and call its writeObject method to send the MyData object. 将socket.getOutputStream()强制转换为ObjectOutputStream ,并调用其writeObject方法发送MyData对象。
  3. On the receiver side, cast socket.getInputStream() to an ObjectInputStream , and call its readObject method to receive the object (you will have to cast it to MyData). 接收方,将socket.getInputStream()强制转换为ObjectInputStream ,并调用其readObject方法以接收对象(您必须将其强制转换为MyData)。

Anyway, I would also consider using RMI . 无论如何,我也将考虑使用RMI For example, you could create a PointServer, register it in the RMI registry, and access it through simple function calls in your client application. 例如,您可以创建一个PointServer,在RMI注册表中注册它,然后通过客户端应用程序中的简单函数调用来访问它。 RMI is much easier to work with than sockets. RMI比套接字更容易使用。 For example, you don't have to design a protocol, you only need to define methods for your distributed objects. 例如,您不必设计协议,只需要为分布式对象定义方法。

Why not use an ObjectInputStream/ObjectOutputStream instead? 为什么不改用ObjectInputStream / ObjectOutputStream?

Here's a piece of code for something I wrote long ago, it will allow you to send any kind of object through the wire so long as it's serializable, obviously: 这是我很久以前写的东西的一段代码,它可以让您通过电线发送任何类型的对象,只要它是可序列化的,显然:

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 is just a "wrapper"/custom class that you can define as having as one of it's properties a Point[]; DataObject只是一个“包装器” /自定义类,您可以将其定义为具有Point []作为其属性之一。 in other words, you could define DataObject as: 换句话说,您可以将DataObject定义为:

import java.io.Serializable;

public class DataObject implements Serializable {

   private Point[] points; //etc - define getter setter for points
}

And you can write it as: 您可以将其编写为:

output = new ObjectOutputStream(communicationSocket
                    .getOutputStream());
output.writeObject(yourDataObject);

Now, you can read this as so: 现在,您可以这样阅读:

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;
}
}

Well, there are some points that you should be aware of, for example, the size of an int 32 or 64 bits, the byte order of the sending and the receiving machines, etc. Also, there should be a protocol to communicate both sockets, I mean, there should be a header in every packets send so that you know how much data you are going to received, I won't deal with that, I assume that you want to send and receive an array of 20 points. 好吧,您应该了解一些要点,例如,int 32或64位的大小,发送方计算机和接收方计算机的字节顺序等。此外,还应该有一个协议来通信两个套接字,我的意思是,每个发送的数据包中都应该有一个标头,以便您知道将要接收多少数据,我不会处理,我假设您要发送和接收一个20点的数组。 In this example it's assumed that both machines are 32 bits, ie an int is 4 bytes in size and that both machines use LITTLE_ENDIAN byte order. 在此示例中,假设两台计算机均为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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM