數據報(Datagram)使網絡層數據單元在介質上傳輸信息的一種邏輯分組格式
它是一種在網絡中傳播的
獨立的
自身包含地址信息的消息
它能否到達目的地
到達的時間
到達時內容是否會變化不能准確知道的
它的通訊雙方是不需要建立連接的
對於一些不需要很高質量的應用程序來說
數據報通訊是一個非常好的選擇
在Java的包中有兩個類DatagramSocket和DatagramPacket
為應用程序中采用數據報通訊方式進行網絡通訊
下面
我想詳細解釋在Java中實現客戶端與服務器之間數據報通訊的方法
請看
一
客戶端應用程序的工作流程
) 首先要建立數據報通訊的Socket
我們可以通過創建一個DatagramSocket對象來實現它
在Java中DatagramSocket類有如下兩種構造方法
a)public DatagramSocket() 構造一個數據報socket
並使其與本地主機任一可用的端口連接
若打不開socket則拋出SocketException異常
b) public DatagramSocket(int port) 構造一個數據報socket
並使其與本地主機指定的端口連接
若打不開socket或socket無法與指定的端口連接則拋出SocketException異常
) 創建一個數據報文包
用來實現無連接的包傳送服務
每個數據報文包是用DatagramPacket類來創建
DatagramPacket對象封裝了數據報包數據
包長度
目標地址
目標端口
作為客戶端要發送數據報文包
要調用DatagramPacket類以如下形式的構造函數創建DatagramPacket對象
將要發送的數據和包文目的地址信息放入對象之中
DatagramPacket(byte bufferedarray[]
int length
InetAddress address
int port)即構造一個包長度為length的包傳送到指定主機指定端口號上的數據報文包
參數length必須小於等於bufferedarry
length
DatagramPacket類提供了四個類來獲取信息
a) public byte[] getData() 返回一個字節數組
包含收到或要發送的數據報中的數據
b) public int getLength() 返回發送或接收到的數據的長度
c) public InetAddress getAddress() 返回一個發送或接收此數據報包文的機器的IP地址
d) public int getPort() 返回發送或接收數據報的遠程主機的端口號
)創建完DatagramSocket和DatagramPacket對象
就可以發送數據報文包了
發送是通過調用DatagramSocket對象的send方法實現
它需要以DatagramPacket對象為參數
將剛才封裝進DatagramPacket對象中的數據組成數據報發出
)當然
我們也可以接收數據報文包
為了接收從服務器返回的結果數據報文包
我們需要創建一個新的DatagramPacket對象
這就需要用到DatagramPacket的另一種構造方式DatagramPacket(byte bufferedarray[]
int length)
即只需指明存放接收的數據報的緩沖區和長度
調用DatagramSocket對象的receive()方法來完成接收數據報的工作
此時需要將上面創建的DatagramPacket對象作為參數
該方法會一直阻塞知道收到一個數據報文包
此時DatagramPacket的緩沖區中包含的就是接收到的數據
數據報文包中也包含發送者的IP地址
發送者機器上的端口號等信息
)處理接收緩沖區內的數據
獲取服務結果
)當通訊完成後
可以使用DatagramSocket對象的close()方法來關閉數據報通訊Socket
當然
Java自己會自動關閉Socket
釋放DatagramSocket和DatagramPacket所占用的資源
但是作為一種良好的編程習慣
還是要顯示的予以關閉
下面我給出一個簡單的利用數據報通訊的客戶端程序
它能夠完成與服務器簡單的通訊
為了直觀
我把它寫成了Applet程序
由於本文不是介紹Applet
所以我只寫了簡要的注釋
對Applet感興趣的朋友親參閱有關書籍
import java
applet
*;
import java
awt
*;
import
*;
import java
io
*;
public final class javaCommunicationClient extends Applet
{
private Label label
label
;
private Panel panel
panel
;
private TextField textfield;
private TextArea textarea;
private DatagramSocket sendSocket
receiveSocket;//聲明發送數據報Socket和接收數據報Socket
private DatagramPacket sendPacket
receivePacket;//聲明發送數據報文包和接收數據報文包
public void init()
{
setBackground(Color
gray);
setLayout(new BorderLayout());//設置一個布局管理器
panel
=new Panel();
panel
setLayout(new BorderLayout());//在容器中放置布局管理器
label
=new Label(
通話紀錄
);
textarea=new TextArea(
);//文本顯示區域
textarea
setText(
歡迎您!
);
panel
add(
North
label
);//將標簽添加到布局管理器中
panel
add(
Center
textarea);
add(
North
panel
);
label
=new Label(
發言
);//創建另一個容器
panel
add(
Center
label
);
textfield=new TextField(
);
textfield
setText(
);
panel
add(
South
textfield);
add(
Center
panel
);
show();
}
public void start()
{
waitForPackets();
}
public void waitForPackets()
/*方法waitForPacket用來監聽來自於服務器的數據報
當獲得數據報後
在文本顯示區域顯示出來
*/
{
try
{
sendSocket=new DatagramSocket();//實例化一個發送數據報Socket對象
receiveSocket= new DatagramSocket(
);//實例化一個接收數據報Socket對象
以
為端口
} catch (SocketException e)//捕獲異常
{
textarea
appendText(
不能打開數據報Socket
或數據報Socket無法與指定端口連接!
);
}
while (true)
{
try
{
byte buf[]=new byte[
];
receivePacket=new DatagramPacket(buf
buf
length);//實例化一個接收數據報文包對象
receiveSocket
receive(receivePacket);//以receivePacket為參數
接受文包
textarea
appendText(
\n服務器
\t
);
byte[] data=receivePacket
getData();
String receivedString=new String(data);
textarea
appendText(receivedString);//將接收到的數據報文報中的數據顯示出來
} catch(IOException e)
{
textarea
appendText(
網絡通訊出現錯誤
問題在
+e
toString());
}
}
}
public boolean action(Event e
Object o)
{
try
{textarea
appendText(
\n客戶端
);
String string=o
toString();
textarea
appendText(string);
byte[] databyte=new byte[
];
string
getBytes(
string
length()
databyte
);
sendPacket=new DatagramPacket(databyte
string
length()
InetAddress
getByName(
)
);//發送數據報
其中你可以用你自己的主機IP替換器中的IP地址
sendSocket
send(sendPacket);
}catch(IOException ioe)
{
textarea
appendText(
網絡通訊出現錯誤
問題在
+ioe
toString());
}
return true;
}
}
二
服務器端應用程序的工作流程
不同於基於數據流通訊方式
在數據報通訊中
通訊雙方之間並不要建立連接
所以
服務器應用程序通訊過程與客戶端應用程序的通訊過程使非常相似的
也要建立數據報通訊DatagramSocket
構建數據報文包DatagramPacket
接收數據報和發送數據報
處理接收緩沖區內的數據
通訊完畢後
關閉數據報通訊Socket
不同的是
服務器應用程序要面向網絡中的所有計算機
所以服務器應用程序收到一個包文後要分析它
得到數據報的源地址信息
這樣才能創建正確的返回結果報文給客戶機
下面我給出了一個數據報通訊的服務器段程序
由於服務器端的相應應用程序和客戶端程序比較相似
所以我不想詳細的注釋
僅列出程序供大家參考
javaCommunicationServer
java
import
*;
import java
io
*;
import java
awt
*;
import java
applet
Applet;
public final class javaCommunicationServer extends Frame
{
private Label label
label
;
private Panel panel
panel
;
private TextField textfield;
private String name
name
;
private TextArea textarea;
private DatagramSocket sendSocket
receiveSocket;
private DatagramPacket sendPacket
receivePacket;
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19271.html