当前位置: 首页 > 面试题库 >

在UDP上发送和接收序列化对象

姜煌
2023-03-14
问题内容

我正在尝试使用UDP将序列化的对象从服务器进程发送到Java中的客户端进程。问题是客户端在接收方法上被阻止。有人可以帮忙吗?

这是用于发送对象的服务器代码:

  ClientModel C1= new ClientModel(100,"Noor","Noor",38,38,"asd");
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  ObjectOutputStream oos = new ObjectOutputStream(baos);
  oos.writeObject(C1);
  oos.flush();
  byte[] Buf= baos.toByteArray();
  packet = new DatagramPacket(Buf, Buf.length, client, port);
  socket.send(packet);

这是用于接收对象的客户端代码:

byte[] buffer = new byte[100000];
packet = new DatagramPacket(buffer, buffer.length );
socket.receive(packet);
System.out.println("packet received");

我只想接收能够重构的对象,但无法接收数据包本身。


问题答案:

我最终不知道要完成什么,但是使用UDP并不是那么容易…主要原因是在DatagramPacket对象的说明中:

数据报包用于实现无连接包传递服务。仅基于该数据包中包含的信息,将每条消息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个数据包的路由可能不同,并且可能以任何顺序到达。无法保证数据包的传递。

使用udp时,一个很好的教程是http://download.oracle.com/javase/tutorial/networking/datagrams/clientServer.html

关于您的屏蔽:

从此套接字接收数据报包。当此方法返回时,DatagramPacket的缓冲区将填充收到的数据。数据报数据包还包含发送者的IP地址以及发送者计算机上的端口号。

该方法将阻塞直到接收到数据报。数据报包对象的长度字段包含接收到的消息的长度。如果消息长于数据包的长度,则消息将被截断。

我没有真正测试过,但是根据描述,我很确定datagramsocket.reseive函数将一直阻塞,直到数据包填满为止(在您的情况下,直到接收到100000个字节为止)。

我建议您从已知长度的数据报包开始,在其中传输实际有效负载的大小。就像是:

public static void main(String[] args) {
    ClientModel c1 = new ClientModel ();
    c1.data = 123;
    c1.name = "test";

    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(c1);
      oos.flush();
      // get the byte array of the object
      byte[] Buf= baos.toByteArray();

      int number = Buf.length;;
      byte[] data = new byte[4];

      // int -> byte[]
      for (int i = 0; i < 4; ++i) {
          int shift = i << 3; // i * 8
          data[3-i] = (byte)((number & (0xff << shift)) >>> shift);
      }

      DatagramSocket socket = new DatagramSocket(1233);
      InetAddress client = InetAddress.getByName("localhost");
      DatagramPacket packet = new DatagramPacket(data, 4, client, 1234);
      socket.send(packet);

      // now send the payload
      packet = new DatagramPacket(Buf, Buf.length, client, 1234);
      socket.send(packet);

      System.out.println("DONE SENDING");
    } catch(Exception e) {
        e.printStackTrace();
    }
}

另一方面,您现在知道自己的尺寸:

public static void main(String[] args) {
    try {
      DatagramSocket socket = new DatagramSocket(1234);

      byte[] data = new byte[4];
      DatagramPacket packet = new DatagramPacket(data, data.length );
      socket.receive(packet);

      int len = 0;
      // byte[] -> int
      for (int i = 0; i < 4; ++i) {
          len |= (data[3-i] & 0xff) << (i << 3);
      }

      // now we know the length of the payload
      byte[] buffer = new byte[len];
      packet = new DatagramPacket(buffer, buffer.length );
      socket.receive(packet);

        ByteArrayInputStream baos = new ByteArrayInputStream(buffer);
      ObjectInputStream oos = new ObjectInputStream(baos);
      ClientModel c1 = (ClientModel)oos.readObject();
      c1.print();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

使用的CientModel类别:

public class ClientModel implements Serializable{
    private static final long serialVersionUID = -4507489610617393544L;

    String name = "";
    int data = 1;

    void print() {
        System.out.println(data +": " + name);
    }
}

我测试了这段代码,它工作正常。希望能有所帮助(我从http://www.tutorials.de/java/228129-konvertierung-
von-integer-byte-
array.html

获得了byte-To-int
信息)

编辑:如评论中所述,使用UDP通常是一个非常糟糕的主意,主要是因为您不知道是否以正确的顺序接收数据包,甚至根本不接收。UDP不能保证这一点。我没有做太多的udp编程,但是(如果我理解正确的话)您可以依靠的唯一部分是,如果您得到一个数据包并且它适合数据报(65,527字节-
参见https://en.wikipedia .org / wiki /
User_Datagram_Protocol),它将包含整个内容。因此,如果您不关心消息的发送顺序以及对象适合数据报的大小,那应该没问题。

Edit2:至于代码:不要按原样使用它。这只是一个示例,ind
UDP您应该只有一种类型的数据包,并且这种数据包的大小已知。这样,您无需发送“尺寸”。如果您使用上面显示的代码,并且丢弃了一个数据包,则下一个数据包的大小将错误(即,第一个数据包被丢弃,突然您正在检查有效负载的第一个字节以获取大小)。



 类似资料:
  • 问题内容: 我想通过套接字通道传输序列化的对象。我想将“ Hi friends”字符串作为序列化对象,然后将此对象写入套接字通道,而在另一端,我想读取相同的对象并检索数据。 我想使用Java来做所有这些事情。这该怎么做?我已经尝试过以下操作,但是在接收方没有得到任何数据。 问题答案: 您的SocketChannel处理似乎不完整,请参阅此 完整 示例以了解SocketChannel传输字节的方法:

  • 本文向大家介绍python UDP(udp)协议发送和接收的实例,包括了python UDP(udp)协议发送和接收的实例的使用技巧和注意事项,需要的朋友参考一下 需要建立2个文件,一个作为客户端,一个作为服务端 文件一 作为客户端client,文件二作为服务端server udp的特点是不需要建立连接 文件一客户端 文件二服务端 注意:先运行文件二在运行文件一 以上这篇python UDP(ud

  • 我需要在node.js中编写一个应用程序,它将一些UDP数据包发送到给定的IP地址和端口,并监听来自相同IP和端口的UDP数据包。我看到的其他示例似乎都提到了客户端和服务器体系结构,其中一边发送,另一边接收。我需要做两个在一个应用程序。 谢谢

  • 我在网上搜索了很多,但是没有找到通过套接字发送对象并按原样接收的解决方案。我知道它需要酸洗,我已经做过了。将其转换为字节,然后从另一方面接收。但如何将这些字节转换为该类型的对象。 这是在客户端将对象转换为StringIO并发送到服务器的代码。在服务器端,我得到字节。现在我正在搜索要再次转换为StringIO的字节,以便获得对象值。 在代码中,对象被包装在StringIO中,并通过套接字发送。任何更

  • 我想使用Qt UDP(不是TCP)套接字传输文件。所以我这样写代码: 看来要传输的Qt UDP数据包的最小大小是8192字节。接收方总是得到第一个数据包,但不能接收其他数据包。 我对Qt和网络编程的经验很少,所以我不知道我的猜想对不对。你能告诉我如何改变这些代码来支持在第一个数据包之后接收数据包,这样我就可以传输大数据了吗?