UDP编程 UDP连接对象的理解和使用

之前写了一个 一个简单的UDP服务端和客户端示例 ,用于入门UDP,当我实际使用时发生了一点问题!

上次使用中我也把连接对象 DatagramSocket 写成了静态的,在类的初始化时使用,可是系统中有很多地方使用,难道我要不断的创建这个类的对象吗?

 

可以这么做,当时有后果,后果就是内存溢出。

UDP是没有状态的,DatagramSocket 创建一次即可,就是开始指向某个地址的端口,而不用每次创建。

由于UDP是无状态的,在创建 DatagramSocket  对象时只是创建了一个指向网络的对象,就像你架设一个大喇叭对着某个方向,可是你并不知道这个方向到底有没有人在听

如果,即使你没有开服务端,创建连接对象并向这个地址放松数据,都是没有问题。你用喇叭向某个方向喊没人听这没有什么!可是当你需要回应时如果一直没有接到响应,超时之后就会报错!

Java代码    收藏代码
  1. package udp;  
  2.   
  3. import java.net.*;  
  4.   
  5. /** 
  6.  * @说明 UDP客户端程序,用于对服务端发送数据,并接收服务端的回应信息 
  7.  * @author cuisuqiang 
  8.  * @version 1.0 
  9.  * @since <a href="mailto:cuisuqiang@163.com">cuisuqiang@163.com</a> 
  10.  */  
  11. public class UdpClientSocket {  
  12.     /** 
  13.      * 连接对象 
  14.      */  
  15.     private static DatagramSocket ds = null;  
  16.     /** 
  17.      * 地址对象 
  18.      */  
  19.     private static SocketAddress address = null;  
  20.       
  21.     /** 
  22.      * 测试客户端发包和接收回应信息的方法 
  23.      */  
  24.     public static void main(String[] args) throws Exception {  
  25.         init();  
  26.         while(true){  
  27.             UdpClientSocket.send(address,"你好,亲爱的!".getBytes());  
  28.             UdpClientSocket.receive();  
  29.             try {  
  30.                 Thread.sleep(3 * 1000);  
  31.             } catch (Exception e) {  
  32.                 e.printStackTrace();  
  33.             }  
  34.         }  
  35.     }  
  36.       
  37.     /** 
  38.      * 对连接和地址初始化 
  39.      */  
  40.     public static void init(){  
  41.         try {  
  42.             ds = new DatagramSocket(8899); // 邦定本地端口作为客户端  
  43.             ds.setSoTimeout(2 * 1000);  
  44.             address = new InetSocketAddress("127.0.0.1",3344);  
  45.         } catch (Exception e) {  
  46.             e.printStackTrace();  
  47.         }  
  48.     }  
  49.       
  50.     /** 
  51.      * 向指定的服务端发送数据信息 
  52.      */  
  53.     public static void send(SocketAddress address,byte[] bytes){  
  54.         try {  
  55.             DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address);  
  56.             ds.send(dp);  
  57.         } catch (Exception e) {  
  58.             e.printStackTrace();  
  59.         }  
  60.     }  
  61.   
  62.     /** 
  63.      * 接收从指定的服务端发回的数据 
  64.      */  
  65.     public static void receive(){  
  66.         try {  
  67.             byte[] buffer = new byte[1024];  
  68.             DatagramPacket dp = new DatagramPacket(buffer, buffer.length);  
  69.             ds.receive(dp);       
  70.             byte[] data = new byte[dp.getLength()];  
  71.             System.arraycopy(dp.getData(), 0, data, 0, dp.getLength());   
  72.             System.out.println("服务端回应数据:" + new String(data));  
  73.         } catch (Exception e) {  
  74.             e.printStackTrace();  
  75.         }  
  76.     }  
  77. }  

 

执行以代码运行结果如下:

Java代码    收藏代码
  1. java.net.SocketTimeoutException: Receive timed out  
  2.     at java.net.PlainDatagramSocketImpl.receive0(Native Method)  
  3.     at java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:136)  
  4.     at java.net.DatagramSocket.receive(DatagramSocket.java:712)  
  5.     at udp.UdpClientSocket.receive(UdpClientSocket.java:69)  
  6.     at udp.UdpClientSocket.main(UdpClientSocket.java:28)  

 

运行超时,但是报错的地方不是创建对象和发送数据,而是接收数据时超时!

 

这个程序一直运行,我们来搞一个服务端:

Java代码    收藏代码
  1. package udp;  
  2.   
  3. import java.net.DatagramPacket;  
  4. import java.net.DatagramSocket;  
  5. import java.net.InetSocketAddress;  
  6. import java.net.SocketAddress;  
  7.   
  8. /** 
  9.  * @说明 UDP服务类 
  10.  * @author cuisuqiang 
  11.  * @version 1.0 
  12.  * @since cuisuqiang@163.com 
  13.  */  
  14. public class UdpServerSocket {  
  15.       
  16.     private static DatagramSocket ds = null;  
  17.     private static SocketAddress address = null;  
  18.       
  19.     /** 
  20.      * 测试方法 
  21.      */  
  22.     public static void main(String[] args) throws Exception {  
  23.         init();  
  24.         System.out.println("---->服务开始监听!<----");  
  25.         while (true) {  
  26.             UdpServerSocket.receive();  
  27.             UdpServerSocket.response(address,"你好,吃了吗!");  
  28.         }         
  29.     }  
  30.       
  31.     public static void init(){  
  32.         try {  
  33.             ds = new DatagramSocket(3344);  
  34.             ds.setSoTimeout(0);  
  35.             address = new InetSocketAddress("127.0.0.1",8899);  
  36.         } catch (Exception e) {  
  37.             e.printStackTrace();  
  38.         }  
  39.     }  
  40.   
  41.     /** 
  42.      * 接收数据包,该方法会造成线程阻塞 
  43.      */  
  44.     public static void receive() {  
  45.         try {  
  46.             byte[] buffer = new byte[1024];  
  47.             DatagramPacket packet = new DatagramPacket(buffer, buffer.length);  
  48.             ds.receive(packet);  
  49.             String info = new String(packet.getData(), 0, packet.getLength());  
  50.             System.out.println("接收信息:" + info);  
  51.         } catch (Exception e) {  
  52.             e.printStackTrace();  
  53.         }  
  54.     }  
  55.   
  56.     /** 
  57.      * 将响应包发送给请求端 
  58.      */  
  59.     public static void response(SocketAddress address,String info){  
  60.         try {  
  61.             DatagramPacket dp = new DatagramPacket(info.getBytes(), info.getBytes().length, address);  
  62.             dp.setData(info.getBytes());  
  63.             ds.send(dp);  
  64.         } catch (Exception e) {  
  65.             e.printStackTrace();  
  66.         }         
  67.     }  
  68. }  

 

运行后客户端可以正常发送和接收数据!

 

如果在实际运用中,我是设置一个系统启动项,来初始化 init 连接对象和地址,具体使用时进行异常捕获就可以了! 

 

如果你的连接对象每次创建,且使用频繁,一般几分钟系统即可搞挂!

<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值