《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,如需转载请自行联系原作者