首页 > 代码库 > java点滴之操纵UDP的类:DatagramSocket和DatagramPacket

java点滴之操纵UDP的类:DatagramSocket和DatagramPacket

1.基本概念:

    a.DatagramPacket与DatagramSocket位于java.net包中

  b.DatagramPacket表示存放数据的数据报,DatagramSocket表示接受或发送数据报的套接字

  c.由这两个类所有构成的网络链接是基于UDP协议,是一种不可靠的协议。

2.DatagramSocket基本用法

DatagramSocket类:创建接收和发送UDP的Socket实例
DatagramSocket():创建实例。通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。 
DatagramSocket(int port):创建实例,并固定监听Port端口的报文。 
DatagramSocket(int port, InetAddress localAddr):这是个非常有用的构建器,当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自LocalAddr的报文,指定ip地址接受的报文.

receive(DatagramPacket d):接收数据报文到d中。receive方法产生一个“阻塞”。 
send(DatagramPacket d):发送报文d到目的地。 
setSoTimeout(int timeout):设置超时时间,单位为毫秒。 
close():关闭DatagramSocket。在应用程序退出的时候,通常会主动释放资源,关闭Socket,但是由于异常地退出可能造成资源无法回收。所以,应该在程序完成时,主动使用此方法关闭Socket,或在捕获到异常抛出后关闭Sock

注意:在创建DatagramSocket类实例时,如果端口已经被使用,会产生一个SocketException的异常抛出,并导致程序非法终止,这个异常应该注意捕获。 

2.DatagramPacket基本用法

 DatagramPacket:用于处理报文,将byte数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成byte数组。 
DatagramPacket(byte[] buf, int length, InetAddress addr, int port):从buf数组中,取出length长的数据创建数据包对象,目标是addr地址,port端口。 
DatagramPacket(byte[] buf, int offset, int length):将数据包中从offset开始、length长的数据装进buf数组。
DatagramPacket(byte[] buf, int length):将数据包中length长的数据装进buf数组。 
getData():它从实例中取得报文的byte数组编码。 

DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):从buf数组中,取出offset开始的、length长的数据创建数据包对象,目标是addr地址,port端口。 


3.代码示例

接受键盘输入后打包,发送该数据包
public class UdpClient  
{  
    // 定义发送数据报的目的地  
    public static final int DEST_PORT = 30000;  
    public static final String DEST_IP = "127.0.0.1";  
    // 定义每个数据报的最大大小为4KB  
    private static final int DATA_LEN = 4096;     
    // 定义接收网络数据的字节数组  
    byte[] inBuff = new byte[DATA_LEN];  
    // 以指定的字节数组创建准备接收数据的DatagramPacket对象  
    private DatagramPacket inPacket =   
        new DatagramPacket(inBuff , inBuff.length);  
    // 定义一个用于发送的DatagramPacket对象  
    private DatagramPacket outPacket = null;  
    public void init()throws IOException  
    {  
        try(  
            // 创建一个客户端DatagramSocket,使用随机端口  
            DatagramSocket socket = new DatagramSocket())  
        {  
            // 初始化发送用的DatagramSocket,它包含一个长度为0的字节数组  
            outPacket = new DatagramPacket(new byte[0] , 0  
                , InetAddress.getByName(DEST_IP) , DEST_PORT);  
            // 创建键盘输入流  
            Scanner scan = new Scanner(System.in);  
            // 不断地读取键盘输入  
            while(scan.hasNextLine())  
            {  
                // 将键盘输入的一行字符串转换成字节数组  
                byte[] buff = scan.nextLine().getBytes();  
                // 设置发送用的DatagramPacket中的字节数据  
                outPacket.setData(buff);  
                // 发送数据报  
                socket.send(outPacket);  
                // 读取Socket中的数据,读到的数据放在inPacket所封装的字节数组中  
                socket.receive(inPacket);  
                System.out.println(new String(inBuff , 0  
                    , inPacket.getLength()));  
            }  
        }  
    }  
    public static void main(String[] args)   
        throws IOException  
    {  
        new UdpClient().init();  
    }  
}  

接受端接收UDP数据包
public class UdpServer  
{  
    public static final int PORT = 30000;  
    // 定义每个数据报的最大大小为4KB  
    private static final int DATA_LEN = 4096;  
    // 定义接收网络数据的字节数组  
    byte[] inBuff = new byte[DATA_LEN];  
    // 以指定字节数组创建准备接收数据的DatagramPacket对象  
    private DatagramPacket inPacket =   
        new DatagramPacket(inBuff , inBuff.length);  
    // 定义一个用于发送的DatagramPacket对象  
    private DatagramPacket outPacket;  
    // 定义一个字符串数组,服务器端发送该数组的元素  
    String[] books = new String[]  
    {  
        "疯狂Java讲义",  
        "轻量级Java EE企业应用实战",  
        "疯狂Android讲义",  
        "疯狂Ajax讲义"  
    };  
    public void init()throws IOException  
    {  
        try(  
            // 创建DatagramSocket对象  
            DatagramSocket socket = new DatagramSocket(PORT))  
        {  
            // 采用循环接收数据  
            for (int i = 0; i < 1000 ; i++ )  
            {  
                // 读取Socket中的数据,读到的数据放入inPacket封装的数组里  
                socket.receive(inPacket);  
                // 判断inPacket.getData()和inBuff是否是同一个数组  
                System.out.println(inBuff == inPacket.getData());  
                // 将接收到的内容转换成字符串后输出  
                System.out.println(new String(inBuff  
                    , 0 , inPacket.getLength()));  
                // 从字符串数组中取出一个元素作为发送数据  
                byte[] sendData = http://www.mamicode.com/books[i % 4].getBytes();  >