溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java中通過數(shù)據(jù)報包輸送對象的方法是什么

發(fā)布時間:2022-01-10 09:15:45 來源:億速云 閱讀:126 作者:iii 欄目:編程語言

這篇文章主要介紹“Java中通過數(shù)據(jù)報包輸送對象的方法是什么”,在日常操作中,相信很多人在Java中通過數(shù)據(jù)報包輸送對象的方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java中通過數(shù)據(jù)報包輸送對象的方法是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

Java 1.1 吸引人的特性之一就是新增了 objectInputStreamObjectOutputStream 這兩個類。有了這個新的 api(ObjectOutputStream 類中的 writeObject(Object o) 方法和 ObjectInputStream 類中的 object readObject()),您就可以隨時獲取運(yùn)行對象的快照,而不管它的對象圖有多復(fù)雜。因為這種快照是通過 ObjectOutputStream 類(OutputStream 類的子類)提供的,所以您很容易將它包裝在其他輸出流中,從而實現(xiàn)所需的任何功能(如 FileOutputStream)。

Java 1.1 中提供的這些新類使得在網(wǎng)上傳輸運(yùn)行對象成為可能。為此,該對象以及那些被引用的對象必須可序列化 -- 即能夠轉(zhuǎn)換為字節(jié)流。幸運(yùn)的是,在 Java 1.1 中,多數(shù)內(nèi)建的類都是可序列化的。但是,某些類是不可序列化的(Object 類就是一個典型的例子)。不過別擔(dān)心。如果您的類繼承自不可序列化的類,您還可以用 ObjectOutputStream 類中的 defaultWriteObject() 方法實現(xiàn)序列化,隨后還可用 ObjectInputStream 類中的 defaultReadObject() 方法解除序列化。

一旦進(jìn)行了序列化,對象就可在網(wǎng)上傳輸了。以下示例說明生成可序列化對象并通過流套接字發(fā)送它的方法:

//對象輸出
import java.NET.*;
import java.io.*;

//要發(fā)送的類樣例: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 為主機(jī)名
 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 類來支持無連接的數(shù)據(jù)報通信。我們可以使用數(shù)據(jù)報通信完成對象輸入/輸出嗎?完成此功能不象使用流套接字那么簡單?問題在于 DatagramSocket 未連接到任何流;為了執(zhí)行發(fā)送和接收操作,DatagramSocket 使用一個字節(jié)數(shù)組作為參數(shù)。

可以想像,為了構(gòu)造數(shù)據(jù)報包,對象必須轉(zhuǎn)換成字節(jié)數(shù)組。如果對象涉及到一個復(fù)雜的對象圖,這種轉(zhuǎn)換可能極難完成。以前發(fā)表的許多文章討論了實現(xiàn)對象序列化的方法 -- 即將 Java 對象打包(序列化)成字節(jié)流以及將字節(jié)流解包為 Java 對象。然而,由于對象圖可能很復(fù)雜,則將常規(guī)對象圖轉(zhuǎn)換成字節(jié)數(shù)組可能需要編寫大量的代碼。

那么,如何避免編寫復(fù)雜的打包代碼呢?以下提供了一種利用數(shù)據(jù)報包傳輸對象的方法,而且無需編寫打包代碼。

Java中通過數(shù)據(jù)報包輸送對象的方法是什么

上圖說明了使用數(shù)據(jù)報傳輸對象時的數(shù)據(jù)流。按以下給出的七個步驟,您就能實現(xiàn)這個數(shù)據(jù)流,它可傳輸任何類型的對象,myObject

  • 第一步。準(zhǔn)備:通過實現(xiàn) Serializable 接口使您的對象(比方說 myObject)可序列化。


  • 第二步。創(chuàng)建 ByteArrayOutputStream 對象,比方說,名為 baoStream。


  • 第三步。用 baoStream 構(gòu)造一個 ObjectOutputStream 對象,比方說 ooStream


  • 第四步。通過調(diào)用 ooStreamwriteObject() 方法將對象 myObject 寫入 baoStream 中。


  • 第五步。使用 baoStreamtoByteArray() 方法從 baoStream 中檢索字節(jié)數(shù)組緩沖區(qū)。


  • 第六步。使用由第五步檢索到的數(shù)組緩沖區(qū)構(gòu)造 DatagramPacket,比方說 dPacket


  • 第七步。通過調(diào)用 DatagramSocketsend() 方法發(fā)送 dPacket。

要接收對象,以逆序完成以上所列各步,用 ObjectInputStream 代替 ObjectOutputStream,同時用 ByteArrayInputStream 代替 ByteArrayOutputStream。

當(dāng)用套接字編程時,sendTo 是無連接協(xié)議中使用的一個標(biāo)準(zhǔn)函數(shù)。為了能夠傳輸對象,我重寫了這個函數(shù)。以下代碼示例展示了如何在 Sender 類中實現(xiàn) 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();

 // 檢索字節(jié)數(shù)組
 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 類中實現(xiàn) receive 方法。recvObjFrom 方法是供接收者接收對象的。您應(yīng)在您的代碼中包含此方法以接收運(yùn)行時對象。

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

人們可能會擔(dān)心字節(jié)數(shù)組的大小 -- 因為當(dāng)您構(gòu)造 ByteArrayOutputStreamByteArrayInputStream 時,您必須指定數(shù)組的大小。既然您不知道運(yùn)行時對象的大小,您就很難指定其大小。運(yùn)行時對象的大小通常是不可預(yù)知的。幸運(yùn)的是,Java 的 ByteArrayInputStreamByteArrayOutputStream 類可根據(jù)需要自動擴(kuò)展其大小。

到此,關(guān)于“Java中通過數(shù)據(jù)報包輸送對象的方法是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI