您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java中通過數據報包輸送對象的方法是什么”,在日常操作中,相信很多人在Java中通過數據報包輸送對象的方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”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 = .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);
}
}
人們可能會擔心字節數組的大小 -- 因為當您構造 ByteArrayOutputStream
或 ByteArrayInputStream
時,您必須指定數組的大小。既然您不知道運行時對象的大小,您就很難指定其大小。運行時對象的大小通常是不可預知的。幸運的是,Java 的 ByteArrayInputStream
和 ByteArrayOutputStream
類可根據需要自動擴展其大小。
到此,關于“Java中通過數據報包輸送對象的方法是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。