Java中通过数据报包输送对象的方法是什么(java,编程语言)

时间:2024-04-29 13:58:47 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

    Java%E4%B8%AD%E9%80%9A%E8%BF%87%E6%95%B0%E6%8D%AE%E6%8A%A5%E5%8C%85%E8%BE%93%E9%80%81%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%96%B9%E6%B3%95%E6%98%AF%E4%BB%80%E4%B9%88

Java 1.1 吸引人的特性之一就是新增了 objectInputStreamObjectOutputStream 这两个类。有了这个新的 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 对象。然而,由于对象图可能很复杂,则将常规对象图转换成字节数组可能需要编写大量的代码。

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

Java中通过数据报包输送对象的方法是什么

上图说明了使用数据报传输对象时的数据流。按以下给出的七个步骤,您就能实现这个数据流,它可传输任何类型的对象,myObject

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


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


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


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


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


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


第七步。通过调用 DatagramSocketsend() 方法发送 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 = .netAddress.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);
}
}

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

本文:Java中通过数据报包输送对象的方法是什么的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:如何实现App打包下一篇:

6 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18