使用DatagramSocket发送、接收数据(1)

 使用DatagramSocket发送、接收数据数组

Java使用DatagramSocket表明UDP协议的Socket,DatagramSocket自己只是码头,不维护状态,不能产生IO 流,它的惟一做用就是接收和发送数据报,Java使用DatagramPacket来表明数据报,DatagramSocket接收和发送的数据都是经过 DatagramPacket对象完成的。服务器

先看一下DatagramSocket的构造器。socket

DatagramSocket():建立一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、本机全部可用端口中随机选择的某个端口。spa

DatagramSocket(int prot):建立一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、指定端口。线程

DatagramSocket(int port, InetAddress laddr):建立一个DatagramSocket实例,并将该对象绑定到指定IP地址、指定端口。设计

经过上面三个构造器中的任意一个构造器便可建立一个DatagramSocket实例,一般在建立服务器时,建立指定端口的 DatagramSocket实例--这样保证其余客户端能够将数据发送到该服务器。一旦获得了DatagramSocket实例以后,就能够经过以下两 个方法来接收和发送数据。code

receive(DatagramPacket p):从该DatagramSocket中接收数据报。对象

send(DatagramPacket p):以该DatagramSocket对象向外发送数据报。开发

从上面两个方法能够看出,使用DatagramSocket发送数据报时,DatagramSocket并不知道将该数据报发送到哪里,而是由 DatagramPacket自身决定数据报的目的地。就像码头并不知道每一个集装箱的目的地,码头只是将这些集装箱发送出去,而集装箱自己包含了该集装箱 的目的地。get

下面看一下DatagramPacket的构造器。

DatagramPacket(byte[] buf,int length):以一个空数组来建立DatagramPacket对象,该对象的做用是接收DatagramSocket中的数据。

DatagramPacket(byte[] buf, int length, InetAddress addr, int port):以一个包含数据的数组来建立DatagramPacket对象,建立该DatagramPacket对象时还指定了IP地址和端口--这就决 定了该数据报的目的地。

DatagramPacket(byte[] buf, int offset, int length):以一个空数组来建立DatagramPacket对象,并指定接收到的数据放入buf数组中时从offset开始,最多放length个字节。

DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):建立一个用于发送的DatagramPacket对象,指定发送buf数组中从offset开始,总共length个字节。

当Client/Server程序使用UDP协议时,实际上并无明显的服务器端和客户端,由于两方都须要先创建一个DatagramSocket 对象,用来接收或发送数据报,而后使用DatagramPacket对象做为传输数据的载体。一般固定IP地址、固定端口的DatagramSocket 对象所在的程序被称为服务器,由于该DatagramSocket能够主动接收客户端数据。

在接收数据以前,应该采用上面的第一个或第三个构造器生成一个DatagramPacket对象,给出接收数据的字节数组及其长度。而后调用 DatagramSocket 的receive()方法等待数据报的到来,receive()将一直等待(该方法会阻塞调用该方法的线程),直到收到一个数据报为止。以下代码所示:

// 建立一个接收数据的DatagramPacket对象  
DatagramPacket packet=new DatagramPacket(buf, 256); 
 // 接收数据报 
  socket.receive(packet);

在发送数据以前,调用第二个或第四个构造器建立DatagramPacket对象,此时的字节数组里存放了想发送的数据。除此以外,还要给 出完整的目的地址,包括IP地址和端口号。发送数据是经过DatagramSocket的send()方法实现的,send()方法根据数据报的目的地址 来寻径以传送数据报。以下代码所示:

// 建立一个发送数据的DatagramPacket对象  
DatagramPacket packet = new DatagramPacket(buf, length, address, port);  
// 发送数据报  
socket.send(packet);

使用DatagramPacket接收数据时,会感受DatagramPacket设计得过于烦琐。开发者只关心该DatagramPacket能 放多少数据,而DatagramPacket是否采用字节数组来存储数据彻底不想关心。但Java要求建立接收数据用的DatagramPacket时, 必须传入一个空的字节数组,该数组的长度决定了该DatagramPacket能放多少数据,这实际上暴露了DatagramPacket的实现细节。接 着DatagramPacket又提供了一个getData()方法,该方法又能够返回Datagram Packet对象里封装的字节数组,该方法更显得有些多余--若是程序须要获取DatagramPacket里封装的字节数组,直接访问传给 DatagramPacket构造器的字节数组实参便可,无须调用该方法。

当服务器端(也能够是客户端)接收到一个DatagramPacket对象后,若是想向该数据报的发送者"反馈"一些信息,但因为UDP协议是面向 非链接的,因此接收者并不知道每一个数据报由谁发送过来,但程序能够调用DatagramPacket的以下3个方法来获取发送者的IP地址和端口。

InetAddress getAddress():当程序准备发送此数据报时,该方法返回此数据报的目标机器的IP地址;当程序刚接收到一个数据报时,该方法返回该数据报的发送主机的IP地址。

int getPort():当程序准备发送此数据报时,该方法返回此数据报的目标机器的端口;当程序刚接收到一个数据报时,该方法返回该数据报的发送主机的端口。

SocketAddress getSocketAddress():当程序准备发送此数据报时,该方法返回此数据报的目标SocketAddress;当程序刚接收到一个数据报时,该方法返回该数据报的发送主机的SocketAddress。

getSocketAddress()方法的返回值是一个SocketAddress对象,该对象实际上就是一个IP地址和一个端口号。也就是 说,SocketAddress对象封装了一个InetAddress对象和一个表明端口的整数,因此使用SocketAddress对象能够同时表明 IP地址和端口。

相关文章
相关标签/搜索