`

如何通过数据包输送对象 -java

 
阅读更多

Java 1.1 吸引人的特性之一就是新增了 ObjectInputStream 和 ObjectOutputStream 这两个类。有了这个API(ObjectOutputStream 类中的 writeObject(Object o) 方法和 ObjectInputStream 类中的 object readObject()),您就可以随时获取运行对象的快照,而不管它的对象图有多复杂。因为这种快照是通过 ObjectOutputStream 类(OutputStream 类的子类)提供的,所以您很容易将它包装在其他输出流中,从而实现所需的任何功能(如 FileOutputStream)。


Java 1.1 中提供的这些新类使得在网上传输运行对象成为可能。为此,该对象以及那些被引用的对象必须可序列化 -- 即能够转换为字节流。幸运的是,在 Java 1.1 中,多数内建的类都是可序列化的。但是,某些类是不可序列化的(Object 类就是一个典型的例子)。不过别担心。如果您的类继承自不可序列化的类,您还可以用 ObjectOutputStream 类中的 defaultWriteObject() 方法实现序列化,随后还可用 ObjectInputStream 类中的 defaultReadObject() 方法解除序列化。

一旦进行了序列化,对象就可在网上传输了。以下示例说明生成可序列化对象并通过流套接字发送它的方法:

//对象输出
import java.net.*;
import java.io.*;

//要发送的类样例:Factory
class Factory implements Serializable
{
  private void writeObject(ObjectOutputStream out) throws IOException
  {
    out.defaultWriteObject();
  }

  private void readObject(ObjectInputStream in)
               throws IOException, ClassNotFoundException
  {
    in.defaultReadObject();
  }
}

public class ShowObjOutput
{
  public static void main(String[] arg)
  {
    try
    {
      ObjectOutputStream os;
      Socket sock = new Socket("panda.cs.uno.edu", 6000); //panda 为主机名
      Factory fa = new Factory();

      os = new ObjectOutputStream( new
             BufferedOutputStream(sock.getOutputStream()));
      os.writeObject(fa);
    }
    catch (IOException ex)
    {}
  }
}


下一示例说明了 ObjectInputStream 如何从流套接字接收对象:

//对象输入
import java.net.*;
import java.io.*;

public class ShowObjInput
{
  public static void main(String[] arg)
  {
    try
    {
      ObjectInputStream is;
      ServerSocket servSock = new ServerSocket(6000);
      Sock sock;

      sock = servSock.accept();
      is = new ObjectInputStream( new
               BufferedInputStream(sock.getInputStream()));
      Factory o = (Factory)is.readObject();
    }
    catch (IOException ex)
    {}
  }
}


除了紧密耦合的套接字之外,Java 还提供了 DatagramSocket 类来支持无连接的数据报通信。我们可以使用数据报通信完成对象输入/输出吗?完成此功能不象使用流套接字那么简单?问题在于 DatagramSocket 未连接到任何流;为了执行发送和接收操作,DatagramSocket 使用一个字节数组作为参数。

可以想像,为了构造数据报包,对象必须转换成字节数组。如果对象涉及到一个复杂的对象图,这种转换可能极难完成。以前发表的许多文章讨论了实现对象序列化的方法 -- 即将 Java 对象打包(序列化)成字节流以及将字节流解包为 Java 对象。然而,由于对象图可能很复杂,则将常规对象图转换成字节数组可能需要编写大量的代码。

那么,如何避免编写复杂的打包代码呢?以下提供了一种利用数据报包传输对象的方法,而且无需编写打包代码。

按以下给出的七个步骤,您就能实现这个数据流,它可传输任何类型的对象,myObject。


第一步。准备:通过实现 Serializable 接口使您的对象(比方说 myObject)可序列化。

第二步。创建 ByteArrayOutputStream 对象,比方说,名为 baoStream。

第三步。用 baoStream 构造一个 ObjectOutputStream 对象,比方说 ooStream。

第四步。通过调用 ooStream 的 writeObject() 方法将对象 myObject 写入 baoStream 中。

第五步。使用 baoStream 的 toByteArray() 方法从 baoStream 中检索字节数组缓冲区。

第六步。使用由第五步检索到的数组缓冲区构造 DatagramPacket,比方说 dPacket。

第七步。通过调用 DatagramSocket 的 send() 方法发送 dPacket。
要接收对象,以逆序完成以上所列各步,用 ObjectInputStream 代替 ObjectOutputStream,同时用 ByteArrayInputStream 代替 ByteArrayOutputStream。

当用套接字编程时,sendTo 是无连接协议中使用的一个标准函数。为了能够传输对象,我重写了这个函数。以下代码示例展示了如何在 Sender 类中实现 send 方法:

import java.io.*;
import java.net.*;

public class Sender
{
  public void sendTo(Object o, String hostName, int desPort)
  {
    try
    {
      InetAddress address = InetAddress.getByName(hostName);
      ByteArrayOutputStream byteStream = new
          ByteArrayOutputStream(5000);
      ObjectOutputStream os = new ObjectOutputStream(new
                              BufferedOutputStream(byteStream));
      os.flush();
      os.writeObject(o);
      os.flush();

      // 检索字节数组
      byte[] sendBuf = byteStream.toByteArray();
      DatagramPacket packet = new DatagramPacket(
                          sendBuf, sendBuf.length, address, desPort);
      int byteCount = packet.getLength();
      dSock.send(packet);
      os.close();
    }
    catch (UnknownHostException e)
    {
      System.err.println("Exception: " + e);
      e.printStackTrace ();
    }
    catch (IOException e)
    { e.printStackTrace(); }
  }
}


以下代码清单说明了如何在 Receiver 类中实现 receive 方法。recvObjFrom 方法是供接收者接收对象的。您应在您的代码中包含此方法以接收运行时对象。

import java.io.*;
import java.net.*;

public class Receiver
{
  public Object recvObjFrom()
  {
    try
    {
      byte[] recvBuf = new byte[5000];
      DatagramPacket packet = new DatagramPacket(recvBuf,
                                                 recvBuf.length);

      dSock.receive(packet);
      int byteCount = packet.getLength();

      ByteArrayInputStream byteStream = new
                                  ByteArrayInputStream(recvBuf);

      ObjectInputStream is = new
           ObjectInputStream(new BufferedInputStream(byteStream));
      Object o = is.readObject();
      is.close();
      return(o);
    }
    catch (IOException e)
    {
      System.err.println("Exception: " + e);
      e.printStackTrace ();
    }
    catch (ClassNotFoundException e)
    { e.printStackTrace(); }

    return(null);
  }
}


人们可能会担心字节数组的大小 -- 因为当您构造 ByteArrayOutputStream 或 ByteArrayInputStream 时,您必须指定数组的大小。既然您不知道运行时对象的大小,您就很难指定其大小。运行时对象的大小通常是不可预知的。幸运的是,Java 的 ByteArrayInputStream 和 ByteArrayOutputStream 类可根据需要自动扩展其大小。

小结
通过利用 Java 的内建序列化代码,我阐述了一种使用数据报包传输对象的方法。正如您所见,技巧就是使用字节数组流将对象流化为字节数组。

分享到:
评论

相关推荐

    工控协议-dnp3-数据包-0-30功能码

    工控协议-dnp3-数据包-0-30功能码

    cnmaps_地理数据包_cnmaps-geo-data.zip

    cnmaps_地理数据包_cnmaps-geo-data

    手机号码归属地数据包-2018-附PHPdome

    标题中的“手机号码归属地数据包-2018-附PHPdome”指的是一个包含2018年手机号码归属地信息的数据集合,其中包含了使用PHP编程语言处理和展示这些数据的示例代码,即PHPdome。PHPdome可能是一个工具或框架,用于便捷...

    NPcap捕获数据包,pcap-next-ex

    下面我们将深入探讨NPcap、`pcap_next_ex`函数以及如何通过它们进行数据包捕获。 首先,NPcap是一个网络包捕获库,它是libpcap的Windows版本,广泛用于开发网络监控工具,如Wireshark。NPcap提供了与libpcap兼容的...

    Wireshark数据包分析实战-第2版-包含配套文件-人工添加了书签

    通过实例分析,读者将学会如何分析这些协议的数据包,识别网络通信问题,比如丢包、延迟、错误序列号等问题。此外,书中还会涉及网络安全相关的分析,如嗅探、密码分析和安全漏洞检测,以提高读者对网络威胁的防范...

    Hyo原创TCPIP数据包分析工具-TCP数据包.rar

    通过介绍TCP连接的建立过程(通常称作三阶段握手),进而展开讲述TCP连接的建立与终止的过程,并通过对实验数据编写程序分析截获的一个客户端预多个WEB服务器之间的通信数据包,以得到TCP包的内部连接情况,持续时间...

    网络数据包监控程序-课程设计(含课程报告和代码).rar

    网络数据包监控程序-课程设计(含课程报告和代码)

    手把手教你捕获数据包-winpcap-混杂模式设定

    手把手教你捕获数据包-winpcap-混杂模式设定 捕获数据包的实现原理 在通常情况下,网络通信的套接字程序只能响应与自己硬件地址相匹配的或是以广播形式发出的数据帧,对于其他形式的数据帧比如已到达网络接口但却...

    Hyo原创TCPIP数据包分析工具-TCP_IP.rar

    通过介绍TCP连接的建立过程(通常称作三阶段握手),进而展开讲述TCP连接的建立与终止的过程,并通过对实验数据编写程序分析截获的一个客户端预多个WEB服务器之间的通信数据包,以得到TCP包的内部连接情况,持续时间...

    中职网络安全数据包分析data-1.pcapng

    本文将围绕Wireshark这一强大的网络封包分析工具,探讨如何通过该数据包分析网络安全相关的知识点。 首先,Wireshark作为网络分析的利器,它能捕获并显示网络通信过程中的每一个数据包,帮助我们了解网络流量的实时...

    24L01+带数据包的ACK-用于双向传输.doc

    24L01+带数据包的ACK用于双向传输 本文主要介绍了使用24L01+芯片实现双向传输的方法,即使用带数据包的ACK应答传输。作者首先介绍了为什么选择使用24L01+芯片,并分享了其使用经验和遇到的问题。然后,作者详细介绍...

    udp数据包转发器-UDP协议

    3. **安全过滤**:在防火墙或代理服务器中,可以使用UDP转发器对数据包进行过滤,只允许特定类型或特定地址的数据包通过。 4. **负载均衡**:可以利用UDP转发器将流量分散到多个服务器,提高服务的可用性和性能。 ...

    1.1 数据包分析与数据包嗅探器 - Wireshark 数据包分析实战(第 3 版) - 知乎书店1

    声明提要书的赞誉么购买本书与法使本书例捕获件科技基会与持章数据包分析技术与络基础1.1数据包分析与数据包嗅探器1.1.1评估数据包嗅探器1.1.2数据包

    B.1 数据包表现形式 - Wireshark 数据包分析实战(第 3 版) - 知乎书店1

    数据包表现形式的理解和应用 在 Wireshark 数据包分析实战(第 3 版)中,数据包表现形式是指数据包能够以多种形式被解析和表示的方式。这种形式可以是二进制数据、十六进制数据或其他形式。二进制数据是数据信息在...

    dragonite-java,Java中的Dragonite项目主存储库.zip

    在提供的压缩包文件“dragonite-java-master”中,包含了Dragonite项目的源代码,开发人员可以通过阅读和学习这些源代码,了解其实现细节,并根据自身项目需求进行二次开发或优化。此外,对于想要贡献代码的开发者,...

    B.2 使用数据包结构图 - Wireshark 数据包分析实战(第 3 版) - 知乎书店1

    通过这种方式,数据包结构图使分析人员能够不依赖于协议的具体知识,快速识别和解读数据包的关键元素。这对于网络调试、安全审计和性能优化等工作至关重要。掌握这种技能可以极大地提高对网络通信的理解,从而解决...

    7.4.1 Packet Tracer - Implement DHCPv4

    7.4.1 Packet Tracer - Implement DHCPv4 Cisco Packet Tracer 思科模拟器 正确答案文件 由于程序问题无法保存激活DHCP端口配置 另加满分步骤截图 可直接上交正确答案文件 本答案版权归mewhaku所有,严禁再次...

    Bravo-1.pcapng

    有题可私

    java实现ip数据包的分析

    通过这些库,开发者可以访问底层网络接口,捕获经过的数据包,并进行自定义的分析。 首先,让我们简要了解 IP 数据包的结构。IP 数据包主要由头部和数据两部分组成。头部包含了源 IP 地址、目标 IP 地址、服务类型...

    udt-java 可靠UDP传输 源码

    通过对udt-java项目的源码学习,我们可以了解到如何在Java环境下构建一个可靠的数据传输协议,这对于网络编程、大数据传输以及高性能计算等领域有着重要的实践价值。同时,这个项目也是研究可靠UDP传输的一个很好的...

Global site tag (gtag.js) - Google Analytics