《Java编程艺术》章节选登。作者:高永强 清华大学出版社 (即将出版)
23.2.5 Datagram编程 (1)
数据报表
Datagram
,或称数报式数据传输技术,利用
UDP
通讯协议(
User Datagram Protocol
),进行用户
-
服务器间的数据传递,但
Java
虚拟机将
UDP
底层通讯细节隐藏,编程人员不必顾及其通讯协议和过程,只需利用
java.net
包中提供的
API
类
DatagramSocket
和
DatagramPacket
进行程序设计,调用适当的方法,实现用户
-
服务器编程。其中
DatagrameScoket
用来创建端口间的通讯,而
DatagramPacket
用来获取通过网络地址和端口以邮包方式(
Packet
)发送来的信息。表
23.4
列出了
java.net
包中
DataramSocket
和
DataramPacket
的常用构造器以及方法。
表
23.4 DatagramSocket
和
DatagramPacket
类的常用构造器以及方法
构造器
/
方法
|
解
释
|
DatagramSocket(int port,InetAdrress
address)
|
按指定端口和互联网地址创建对象。
|
close()
|
关闭插座连接。
|
connect(InetAddress address, int port)
|
按指定互联网地址和端口连接。
|
disconnect()
|
断开当前的连接。
|
InetAddress getInetAddress()
|
返回当前数报插座的互联网地址。
|
InetAddress getLocalAddress()
|
返回当前数报插座的本机地址
|
int getPort()
|
返回当前数报插座的连接端口。
|
int getLocalPort()
|
返回当前数报插座的本机连接端口。
|
receive(DatagramPacket packet)
|
接收当前数报插座的邮件。
|
send(DatagramPacket packet)
|
发送当前数报插座的邮件。
|
DatagramPacket(byte[] buf, int length)
|
按指定缓冲数组合长度创建获取邮包的对象。
|
InetAddress getAddress()
|
返回当前进行邮包传送的互联网地址。
|
Byte[] getData()
|
返回当前发送或接收数据缓冲数组。
|
int getLength()
|
返回当前发送或接收数据的长度。
|
int getPort()
|
返回当前发送或接收数据的端口。
|
注意
DatagramSocket
和
DatagramPacket
抛出检查性异常,程序中必须提供处理这些异常的代码。具体实例见下面的讨论。
下面的例子利用
DatagramSocket
和
DatagramPacket
,模拟用户
-
服务器通讯,将用户
的英文输入,通过邮包发送到服务器端程序,转换为大写字母,并将结果传回到用户屏
幕。其功能类似于在
Socket
和
ServerSocket
讨论过的程序,但增加了统计并返回邮包长度的操作。图
23.7
显示了这个例子的一个典型运行结果。图上方为服务器端程序运行后的
截图。(注:截图未能显示。请参考原书)
图
23.7
利用
Datagram
的典型运行结果
如下是利用
Datagram
编写的服务器端程序的代码:
//
这个程序存在本书配套资源目录
Ch23
名为
DatagramServerTest.java
import java.io.
*
;
import java.net.
*
;
public class DatagramServerTest {
public static void main(String[] args) {
System.out.println(\"Welcome! The server is running....\");
String line = \"Datagram packet from server: I love Java programming.\\n\";
String promptString = line.toUpperCase() + \"Enter quit to STOP\";
try {
DatagramSocket socket = new DatagramSocket(1688);
//
创建指定端口的
Datagram
DatagramPacket receivePacket; //
声明接收邮包
byte[] buf = new byte[256]; //
缓冲器
receivePacket = new DatagramPacket(buf, buf.length);
//
创建接收邮包
socket.receive(receivePacket); //
接收邮包
buf = promptString.getBytes(); //
内容至缓冲
InetAddress address = receivePacket.getAddress();
//
得到接收地址
int port = receivePacket.getPort();//
得到接收端口
sending(socket, buf, buf.length, address, port);
//
调用发送邮包方法
while (true) {
buf = new byte[256]; //
清除缓冲
receivePacket = new DatagramPacket(buf, buf.length);
//
创建新邮包
socket.receive(receivePacket); //
接收
String receive = new String(receivePacket.getData()); //
得到邮包内容
buf = receive.toUpperCase().getBytes();
//
内容转成大写并送往缓冲
sending(socket, buf, buf.length, address, port);//
发送
buf = new byte[256]; //
清除缓冲
String wordCount = \"(Converting from server and packet length: \" + receive.trim().length() + \")\";
receivePacket = new DatagramPacket(buf, buf.length); //
创建新邮包
socket.receive(receivePacket); //
接收
buf = wordCount.getBytes(); //
发件内容送往缓冲
sending(socket, buf, buf.length, address, port);
//
调用发送方法
}
}
catch (IOException e) {
e.printStackTrace();
}
}
//
发送邮件方法
public static void sending(DatagramSocket socket, byte[] buf, int length, InetAddress address, int port) {
DatagramPacket sendPacket = new DatagramPacket(buf, length, address, port);
try {
socket.send(sendPacket); //
发送
}catch (IOException e) {
e.printStackTrace();
}
}
}
代码中首先接收用户端发送过来的一个空邮包,并利用这个邮包发送慰问和提示信息到用户。在循环中,接收用户发来的邮包内容,并将其转换成大写字母、统计字符串即邮包长度,调用自定义静态方法
sending()
将结果邮包发还给发来的用户。代码中在重新利用缓冲器发送新内容时,利用重新定义缓冲器来清除其原有内容。(待续
本文转自高永强51CTO博客,原文链接: http://blog.51cto.com/yqgao/157391
,如需转载请自行联系原作者