当前位置:天才代写 > tutorial > JAVA 教程 > Java网络编程基本(三) Datagram类利用要领

Java网络编程基本(三) Datagram类利用要领

2017-11-11 08:00 星期六 所属: JAVA 教程 浏览:638

副标题#e#

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( ) 返回数据包中的方针地点的主机端标语。


#p#副标题#e#

发送和吸收数据包还需要发送和吸收数据包的套接字,即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 =====================

#p#分页标题#e#

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.

#p#副标题#e#

【措施注解】

在第11~19行我们用for轮回以端标语为参数实例化DatagramSocket,个中端标语从1024到65535。假如在实例进程中堕落,会抛出SocketException异常。我们按照这个异常就可以判定出哪些端口被占用,哪些照旧空闲的。值得一提的是,我们在实例化了DatagramSocket后,挪用了close()封锁它。作为一种好的作风,应该遵循。端标语在1024以下的系统大概会用到,好比HTTP默认为80端口,FTP默认为21端口,等等,所以我们从1024端口开始探查。

套接字工具也有相应的要领,譬喻发送数据包的要领尚有吸收数据包的要领,先容如下。

pubic void close() 当我们建设一个套接字后,用该要领封锁套接字。

public int getLocalPort() 返回当地套接字的正在监听的端标语。

public void receive(DatagramPacket p) 从网络上吸收数据包并将其存储在DatagramPacket工具p中。p中的数据缓冲区必需足够大,receive()把尽大概多的数据存放在p中,假如装不下,就把其余的部门扬弃。吸收数据堕落时会抛出IOException异常。

public Void Send(DatagramPacket p) 发送数据包,堕落时会产生IOException异常。

下面,我们具体表明在Java中实现客户端与处事器之间数据报通信的要领。

应用措施的事情流程如下:

(1)首先要成立数据报通信的Socket,我们可以通过建设一个DatagramSocket工具实现它,在Java中DatagramSocket类有如下两种结构要领:

public DatagramSocket() 结构一个数据报socket,并使其与当田主机任一可用的端口毗连。若打不开socket则抛出SocketException异常。

public DatagramSocket(int port) 结构一个数据报socket,并使其与当田主机指定的端口毗连。若打不开socket或socket无法与指定的端口毗连则抛出SocketException异常。

(2)建设一个数据报文包,用来实现无毗连的包传送处事。每个数据报文包用DatagramPacket类建设,DatagramPacket工具封装了数据报包数据、包长度、方针地点和方针端口。客户端要发送数据报文包,要挪用DatagramPacket类以如下形式的结构函数建设DatagramPacket工具,将要发送的数据和包文目标地点信息放入工具之中。DatagramPacket(byte bufferedarray[],int length,InetAddress address,int port)即结构一个包长度为length的包传送到指定主机指定端标语上的数据报文包,参数length必需小于便是bufferedarry.length。

DatagramPacket类提供了4个类获取信息:

public byte[] getData() 返回一个字节数组,包括收到或要发送的数据报中的数据。

public int getLength() 返回发送或吸收到的数据的长度。

public InetAddress getAddress() 返回一个发送或吸收此数据报包文的呆板的IP地点。

public int getPort() 返回发送或吸收数据报的长途主机的端标语。

(3)建设完DatagramSocket和DatagramPacket工具,就可以发送数据报文包了。发送是通过挪用DatagramSocket工具的send要领实现,它需要以DatagramPacket工具为参数,将适才封装进DatagramPacket工具中的数据构成数据报发出。

(4)虽然,我们也可以吸收数据报文包。为了吸收从处事器返回的功效数据报文包,我们需要建设一个新的DatagramPacket工具,这就需要用到DatagramPacket的另一种结构方法DatagramPacket(byte bufferedarray[],int length),即只需指明存放吸收的数据报的缓冲区和长度。挪用DatagramSocket工具的receive()要领完成吸收数据报的事情,此时需要将上面建设的DatagramPacket工具作为参数,该要了解一直阻塞直到收到一个数据报文包,此时DatagramPacket的缓冲区中包括的就是吸收到的数据,数据报文包中也包括发送者的IP地点,发送者呆板上的端标语等信息。

(5)处理惩罚吸收缓冲区内的数据,获取处事功效。

#p#分页标题#e#

(6)当通信完成后,可以利用DatagramSocket工具的close()要领封锁数据报通信Socket。虽然,Java会自动封锁Socket,释放DatagramSocket和DatagramPacket所占用的资源。可是作为一种精采的编程习惯,照旧要显式地予以封锁。

#p#副标题#e#

3 实例:操作数据报通信的C/S措施

示例12-10给出了一个简朴的操作数据报通信的客户端措施,它可以或许完成与处事器简朴的通信。

【措施源代码】

1 // ==================== Program Description ===================

2 // 措施名称:示例12-10: UDPServer.java
3 // 措施目标:建设UDP处事器
4 //=============================================================
5 import java.net.*;
6 import java.io.*;
7
8 public class UDPServer
9 {
10 static public void main(String args[])
11 {
12 try {
13 DatagramSocket receiveSocket = new DatagramSocket(5000);
14 byte buf[]=new byte[1000];
15 DatagramPacket receivePacket=new DatagramPacket(buf,buf.length);
16 System.out.println("startinig to receive packet");
17 while (true)
18 {
19 receiveSocket.receive(receivePacket);
20 String name=receivePacket.getAddress().toString();
21 System.out.println("\n来自主机:"+name+"\n端口:"
22 +receivePacket.getPort());
23 String s=new
String(receivePacket.getData(),0,receivePacket.getLength());
24 System.out.println("the received data: "+s);
25 }
26 }
27 catch (SocketException e) {
28 e.printStackTrace();
29 System.exit(1);
30 }
31 catch(IOException e) {
32 System.out.println("网络通信呈现错误,问题在"+e.toString());
33 }
34 }
35 }

【措施输出功效】

startinig to receive packet

来自主机:/166.111.172.20

端口:3456

the received data: hello! this is the client

【措施注解】

第13行和第15行别离实例化了一个DatagramSocket工具receiveSocket和一个DatagramPacket工具receivePacket,都是通过挪用各自的结构函数实现的,为成立处事器做好筹备。在while这个永久轮回中,receiveSocket这个套接字始终实验receive()要领吸收DatagramPacket数据包,当吸收到数据包后,就挪用DatagramPacket的一些成员要领显示一些数据包的信息。在措施中挪用了getAddress()得到地点,getPort()要领得到客户端套接字的端口,getData()得到客户端传输的数据。留意getData( )返回的是字节数组,我们把它转化为字符串显示。在第27~33行我们对措施中产生的SocketException和IOException异常举办了处理惩罚。

#p#副标题#e#

示例12-11是UDP客户端的措施。

【措施源代码】

1 // ==================== Program Description ===================

2 // 措施名称:示例12-11: UDPClient.java
3 // 措施目标:建设UDP客户端
4 //=============================================================
5 import java.net.*;
6 import java.io.*;
7
8 public class UDPClient
9 {
10 public static void main(String args[])
11 {
12 try {
13 DatagramSocket sendSocket=new DatagramSocket(3456);
14 String string="asfdfdfggf";
15 byte[] databyte=new byte[100];
16 databyte=string.getBytes();
17 DatagramPacketsendPacket=new
DatagramPacket(databyte,string.length(),
18 InetAddress.getByName("163.121.139.20"),
5000);
19 sendSocket.send(sendPacket);
20 System.out.println("send the data: hello ! this is the client");
21 }
22 catch (SocketException e) {
23 System.out.println("不能打开数据报Socket,或数据报Socket无法与指定
24 端口毗连!");
25 }
26 catch(IOException ioe) {
27 System.out.println("网络通信呈现错误,问题在"+ioe.toString());
28 }
29 }
30 }

【措施输出功效】

send the data: hello !this is the clientsend the data: hello !this is the client

【措施注解】

第13行用DatagramSocket的结构函数实例化一个发送数据的套接字sendSocket。第17~18行实例化了一个DatagramPacket,个中数据包要发往的目标地是163.121.139.20,端口是5000。当结构完数据包后,就挪用send( )要领将数据包发送出去。

#p#副标题#e#

4 组播套接字

在Java中,可以用java.net.MulticastSocket类组播数据。组播套接字是DatagramSocket的子类,界说如下:

public class MulticastSocket extends DatagramSocket

结构要领有两个:

public MulticastSocket ( ) throws SocketException

public MulticastSocket (int port ) throws SocketException

以上两个要领都是建设组播套接字,第一个要领没有端标语,第二个指定了端标语。

常用的要领如下:

public void joinGroup(InetAddress address) throws IOException

成立了MulticastSocket工具后,为了发送可能吸收组播包,必需用joinGroup要领插手一个组播组。若插手的不是组播地点将触发IOException异常。

public void leaveGroup(InetAddress address)throws IOException

#p#分页标题#e#

假如不想吸收组播包了,就挪用leaveGroup要领。措施就发信息到组播路由器,通知它向此用户发送数据。若想分开的地点不是组播地点就触发IOException异常。

public void send(DatagramPacket packet, byte, ttl) throws IOExceptin

发送组播包的要领与DatagramSocket发送数据相似。个中ttl是保留时间,巨细在0~255之间。

public void receive(DatagramPacket p) 与DatagramSocket的吸收要领没有不同。

public void setTimeToLive(int ttl )throws IOException 配置套接字发出的组播包中的默认ttl数值。

public int getTimeToLive( ) throws IOException 返回ttl数值。

利用组播套接字发送数据的进程是首先用MulticastSocket()结构器建设MulticastSocket类,然后操作MulticastSocket类的joinGroup()要领插手一个组播组,之后建设DatagramPacket数据包,最后挪用MulticastSocket类的send()要领发送组播包。

发送组播包的代码如下:

try {
InetAddress address = InetAddress.getByName (www.mmm.net) ;
byte[ ] data=" java networking";
int port =5000;
DatagramPacket datap =new DatagramSocket
(data ,data.length( ),address,port);
MulticastSocket muls =new MulticastSocket ( );
muls.send(datap );
}
catch(IOException ie) {
}

利用组播套接字吸收数据的进程是首先用MulticastSocket()结构器建设MulticastSocket类,然后操作MulticastSocket类的joinGroup()要领插手一个组播组,之后用receive()要领吸收组播包。我们发明其进程与UDP包的进程很相似,区别是要插手一个组播组。

#p#副标题#e#

5 实例:组播套接字C/S措施

下面的措施示例12-12说明白组播套接字的根基用法。

【措施源代码】

1 // ==================== Program Description =====================

2 // 措施名称:示例12-12: MulticastServer.java
3 // 措施目标:建设一个组播处事器
4 //==========================================================
5 import java.io.*;
6 import java.net.*;
7 import java.util.*;
8
9 class QuoteServerThread extends Thread
10 {
11 protected DatagramSocket socket = null;
12 protected BufferedReader in = null;
13 protected boolean moreQuotes = true;
14
15 public QuoteServerThread() throws IOException {
16 this("QuoteServerThread");
17 }
18
19 public QuoteServerThread(String name) throws IOException {
20 super(name);
21 socket = new DatagramSocket(4445);
22
23 try {
24 in = new BufferedReader(new FileReader("one-liners.txt"));
25 } catch (FileNotFoundException e) {
26 System.err.println("Could not open quote file.
Serving time instead.");
27 }
28 }
29
30 public void run() {
31 while (moreQuotes) {
32 try {
33 byte[] buf = new byte[256];
34
35 // 获取请求
36 DatagramPacket packet = new DatagramPacket(buf, buf.length);
37 socket.receive(packet);
38
39 // 举办响应
40 String dString = null;
41 if (in == null)
42 dString = new Date().toString();
43 else
44 dString = getNextQuote();
45 buf = dString.getBytes();
46
47 // 向用户发送响应
48 InetAddress address = packet.getAddress();
49 int port = packet.getPort();
50 packet = new DatagramPacket(buf, buf.length, address, port);
51 socket.send(packet);
52 }
53 catch (IOException e) {
54 e.printStackTrace();
55 moreQuotes = false;
56 }
57 }
58 socket.close();
59 }
60
61 protected String getNextQuote() {
62 String returnValue = null;
63 try {
64 if ((returnValue = in.readLine()) == null) {
65 in.close();
66 moreQuotes = false;
67 returnValue = "No more quotes. Goodbye.";
68 }
69 } catch (IOException e) {
70 returnValue = "IOException occurred in server.";
71 }
72 return returnValue;
73 }
74 }
75
76 class MulticastServerThread extends QuoteServerThread
77 {
78 private long FIVE_SECONDS = 5000;
79
80 public MulticastServerThread() throws IOException {
81 super("MulticastServerThread");
82 }
83
84 public void run() {
85 while (moreQuotes) {
86 try {
87 byte[] buf = new byte[256];
88
89 // 结构引用
90 String dString = null;
91 if (in == null)
92 dString = new Date().toString();
93 else
94 dString = getNextQuote();
95 buf = dString.getBytes();
96
97 // 发送
98 InetAddress group = InetAddress.getByName("136.122.133.1");
99 DatagramPacket packet =new
DatagramPacket(buf,buf.length,group,
100 4446);
101 socket.send(packet);
102
103 // 休眠
104 try {
105 sleep((long)(Math.random() * FIVE_SECONDS));
106 }
107 catch (InterruptedException e) { }
108 }
109 catch (IOException e) {
110 e.printStackTrace();
111 moreQuotes = false;
112 }
113 }
114 socket.close();
115 }
116 }
117
118 public class MulticastServer {
119 public static void main(String[] args) throws java.io.IOException {
120 new MulticastServerThread().start();
121 }
122 }

#p#副标题#e#

【措施注解】

#p#分页标题#e#

处事器措施由3个类构成:QuoteServerThread,MulticastServerThread和MulticastServer。它们的干系是:QuoteServerThread担任自线程类,而MulticastServerThread类担任自类QuoteServerThread。这个措施主要的部门在QuoteServerThread和MulticastServerThread。QuoteServerThread类有两个结构函数,个中在结构函数QuoteServerThread(String name)中,初始化了DatagramSocket套接字并打开了文件one-liners.txt,在这个文件中存有处事器发送的字符串。

在QuoteServerThread类的run()函数中,处事器端套接字吸收来自客户端的数据包,并从文件中读取数据,把信息发给客户端。

MulticastServerThread类中重载了run( )要领,实现的成果基内情同,在发完处事器的信息后,用sleep( )函数遏制处理惩罚了一个随机的时间。

在MultiServer类中,用 new MulticastServerThread().start()开始处事器线程。我们此刻只是存眷其根基思想。

示例12-13是UDP组播的客户端措施。

【措施源代码】

1 // ==================== Program Description =====================

2 // 措施名称:示例12-13: MulticastClient.java
3 // 措施目标:UDP组播客户端
4 //====================>7??:示例1D====================================
5 import java.io.*;
6 import java.net.*;
7 import java.util.*;
8
9 public class MulticastClient
10 {
11 public static void main(String[] args) throws IOException
12 {
13 MulticastSocket socket = new MulticastSocket(4446);
14 InetAddress address = InetAddress.getByName("136.122.133.1");
15 socket.joinGroup(address);
16 DatagramPacket packet;
17
18 for (int i = 0; i < 5; i++)
19 {
20 byte[] buf = new byte[256];
21 packet = new DatagramPacket(buf, buf.length);
22 socket.receive(packet);
23 String received = new String(packet.getData());
24 System.out.println("Quote of the Moment: " + received);
25 }
26
27 socket.leaveGroup(address);
28 socket.close();
29 }
30 }

【措施输出功效】

Quote of the Moment: Give me ambiguity or give me something else.
Quote of the ME7??:示例1oment: I.R.S.: We've got what it takes to take what you've got!
Quote of the Moment: We are born naked, wet and hungry. Then things get worse.
Quote of the Moment: Make it idiot proof and someone will make a better idiot.
Quote of the Moment: He who laughs last thinks slowest!

【措施注解】

在客户端的main()要领中,第13行实例化了一个MulticastSocket工具socket,然后用join()要领插手了组播组136.122.133.1。在for轮回中吸收了5个数据包,并把数据包中的内容显示出来(第18~25行)。最后在第27行分开组播组(leaveGroup)。

 

    关键字:

天才代写-代写联系方式