将想法与焦点和您一起共享

Java网络编程基础(三) Datagram类使用方法发布者:本站     时间:2020-05-06 16:05:13

Datagram(数据包)是一种尽力而为的传送数据的方式,它只是把数据的目的地记录在数据包中,然后就直接放在网络上,系统不保证数据是否能安全送到,或者什么时候可以送到,也就是说它并不保证传送质量。

1 UDP套接字

数据报(Datagram)是网络层数据单元在介质上传输信息的一种逻辑分组格式,它是一种在网络中传播的、独立的、自身包含地址信息的消息,它能否到达目的地、到达的时间、到达时内容是否会变化不能准确地知道。它的通信双方是不需要建立连接的,对于一些不需要很高质量的应用程序来说,数据报通信是一个非常好的选择。还有就是对实时性要求很高的情况,比如在实时音频和视频应用中,数据包的丢失和位置错乱是静态的,是可以被人们所忍受的,但是如果在数据包位置错乱或丢失时要求数据包重传,就是用户所不能忍受的,这时就可以利用UDP协议传输数据包。在Java的java.net包中有两个类DatagramSocket和DatagramPacket,为应用程序中采用数据报通信方式进行网络通信。

使用数据包方式首先将数据打包,Java.net包中的DategramPacket类用来创建数据包。数据包有两种,一种用来传递数据包,该数据包有要传递到的目的地址;另一种数据包用来接收传递过来的数据包中的数据。要创建接收的数据包,通过DatagramPackett类的方法构造:

public DatagramPacket(byte ibuft[],int ilength)

public DatagramPacket( byte ibuft[],int offset ,int ilength)

ibuf[]为接受数据包的存储数据的缓冲区的长度,ilength为从传递过来的数据包中读取的字节数。当采用第一种构造方法时,接收到的数据从ibuft[0]开始存放,直到整个数据包接收完毕或者将ilength的字节写入ibuft为止。采用第二种构造方法时,接收到的数据从ibuft[offset]开始存放。如果数据包长度超出了ilength,则触发IllegalArgument-Exception。不过这是RuntimeException,不需要用户代码捕获。示范代码如下:

byte[ ] buffer=new byte[8912];

DatagramPacket datap=new DatagramPacket(buffer ,buffer.length( ));

创建发送数据包的构造方法为:

public DatagramPacket(byt ibuf[],int ilength,InetAddrss iaddr,int port)

public DatagramPacket(byt ibuf[],int offset , int ilength,InetAddrss iaddr,int port)

iaddr为数据包要传递到的目标地址,port为目标地址的程序接受数据包的端口号(即目标地址的计算机上运行的客户程序是在哪一个端口接收服务器发送过来的数据包)。ibuf[]为要发送数据的存储区,以ibuf数组的offset位置开始填充数据包ilength字节,如果没有offset,则从ibuf数组的0位置开始填充。以下示范代码是要发送一串字符串:


String s = new String("java networking");
byte[ ] data=s.getbytes();
int port=1024;
try{
InetAddress ineta= InetAddress.getByName(" 169.254.0.14");
DatagramPacket datap=new DatagramPacket
(data ,data.length( ),ineta,port);
}
catch(IOException e) {
}
 

数据包也是对象,也有操作方法用来获取数据包的信息,这是很有用的。其方法如下:

public InetAddress getAddress() 如果是发送数据包,则获得数据包要发送的目标地址,但是如果是接收数据包则返回发送此数据包的源地址。

 

public byte[]getData()

返回一个字节数组,其中是数据包的数据。如果想把字节数组转换成别的类型就要进行转化。如果想转化成String类型,可以进行以下的处理,设DatagramPacket datap为:

String s = new String(datap.getbytes());

public int getLength() 获得数据包中数据的字节数。

pubic int getPort( ) 返回数据包中的目标地址的主机端口号。

发送和接收数据包还需要发送和接收数据包的套接字,即DatagramSocket对象,DatagramSocket套接字在本地机器端口监听是否有数据到达或者将数据包发送出去。其构造方法如下。

public DatagramSocket() 用本地机上任何一个可用的端口创建一个套接字,这个端口号是由系统随机产生的。使用方法如下:


try{
DatagramSocket datas=new DatagramSocket( );
//发送数据包
}
catch(SocketException e){
}
 

这种构造方法没有指定端口号,可以用在客户端。如果构造不成功则触发SocketException异常。

public DatagramSocket(int port)

用一个指定的端口号port创建一个套接字。

当不能创建套接字时就抛出SocketException异常,其原因是指定的端口已被占用或者是试图连接低于1024的端口,但是又没有具备权限。

2 实例:利用DatagramSocket查询端口占用情况

我们可以利用这个异常探查本地机的端口号有没有服务。见示例12-9。

【程序源代码】


1 // ==================== Program Description =====================
2 // 程序名称:示例12-9: UDPScan.java
3 // 程序目的:熟悉DatagramSocket的基本用法,查询端口的占用情况
4 //=========================================================
5 import java.net.*;
6
7 public class UDPScan
8 {
9 public static void main(String args[])
10 {
11 for (int port=1024;port<=65535;port++) {
12 try {
13 DatagramSocket server=new DatagramSocket(port);
14 server.close();
15 }
16 catch(SocketException e) {
17 System.out.println("there is a server in port "+port+".");
18 }
19 }
20 }
21 }
 

【程序输出结果】

there is a server in port 1026.

there is a server in port 1028.

there is a server in port 1046.

there is a server in port 1900.

【程序注解】

在第11~19行我们用for循环以端口号为参数实例化DatagramSocket,其中端口号从1024到65535。如果在实例过程中出错,会抛出SocketException异常。我们根据这个异常就可以判断出哪些端口被占用,哪些还是空闲的。值得一提的是,我们在实例化了DatagramSocket后,调用了close()关闭它。作为一种好的作风,应该遵循。端口号在1024以下的系统可能会用到,比如HTTP默认为80端口,FTP默认为21端口,等等,所以我们从1024端口开始探查。



选择我们,优质服务,不容错过
1. 优秀的网络资源,强大的网站优化技术,稳定的网站和速度保证
2. 15年上海网站建设经验,优秀的技术和设计水平,更放心
3. 全程省心服务,不必担心自己不懂网络,更省心。
------------------------------------------------------------
24小时联系电话:021-58370032