JAVA中的UDP通信小程序

本文探讨了UDP客户端和服务端的实现细节,包括如何处理客户端先于服务器启动的情况,利用SocketTimeoutException避免程序挂起,以及如何使用HashMap存储客户端信息,并自定义打印格式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

刚刚写了一个UDP通信的小程序,遇到几个小问题记录下来备案:

1.客户端异常

客户端的几种异常java已经默认的需要程序员try catch掉了,可是有一种异常java没有默认地帮助程序员考虑,那就是客户端先于服务器端启动,注意,不是服务器端的主机没有开启,而是服务器程序没有启动,这时候我们编写的客户端程序会永久挂起,除非强行关闭。关于这一点,我开始想到使用定时器timer通过三步握手判断,延时3秒,如果还是没有接收到server端发来的欢迎信息则退出程序。可是这种timer方法实践证明并不可行,或者说比较繁琐,因为timer本身会启动一个线程,而DUP的DatagramSocket的receive方法也会启动一个线程,如果两个线程同时在争用一个资源(毫无疑问,肯定是DatagramPacket的一个对象,因为DatagrameSocket会向packet中receive,而timer又要判断packet包中是否有数据),就会出现同步的问题,想解决同步问题也不是没有可能,可以使用syncronize关键字,不过这样一来程序就显得非常繁琐。后来查询SDK文档,发现一个SocketTimeoutException,这样一来就方便多了,代码如下:

 

try{
            DatagramSocket dsSend 
= new DatagramSocket();
            DatagramSocket dsReceive 
= new DatagramSocket(4502);
            DatagramPacket dpReceive 
= new DatagramPacket(buf, 100);
            

            DatagramPacket dp 
= new DatagramPacket(args[0].getBytes(), args[0].length(), InetAddress
                    .getByName(
"172.16.22.250"), 4501);
            dsSend.send(dp);
            dsSend.close();
            dsReceive.setSoTimeout(
2000);
            dsReceive.receive(dpReceive);
            System.out.println(
new String(dpReceive.getData(), 0, dpReceive
                    .getLength()));
            dsReceive.close();

        }
 catch (SocketException e) {
            e.printStackTrace();
        }
 catch (UnknownHostException e) {
            e.printStackTrace();
        }
 catch (IOException e) {
            
if(e instanceof SocketTimeoutException){
                System.out.println(
"time out");
                
return;
            }

            e.printStackTrace();
        }

2.服务器端功能扩展(HashMap)

想实现在server端使用map集合存储客户端数据包发送过来的用户名和客户端的IP地址,所以试着自己查阅SDK使用HashMap,其中put函数很方便地就将一些信息压入map中,在打印输出的时候遇到一点问题:尝试着直接使用System.out.println(map)结果很方便地输出来,可是这并不是一个真正程序员的作风,看来java肯定重写了map的toString函数,在SDK的压缩包中找到了HashMap的源码,看了几遍后发现比较复杂,而且还使用到一个Map.Entry的类,不想过多涉及了,打算自己动手写打印输出的功能。看到HashMap中有一个返还Set类型的KeySet函数,于是新建了一个Set集合,把KeySet保存进去,然后用迭代器迭代这个集合,获得Key集合所有元素,再用HashMap的get函数来get这个key集合中的每一个元素,获得整个Map的Value,这样一来就可以自己控制输出格式了,代码如下:

 

Set keyset = map.keySet();
        Iterator it 
= keyset.iterator();
        
try {
            DatagramSocket dsReceive 
= new DatagramSocket(4501);
            DatagramSocket dsSend 
= new DatagramSocket();
            DatagramPacket dpreceive 
= new DatagramPacket(buf, 100);
            DatagramPacket dpsend;
            
while (true{
                dsReceive.receive(dpreceive);
                map.put(
new String(dpreceive.getData(), 0, dpreceive
                        .getLength()), dpreceive.getAddress().toString());
                dpsend 
= new DatagramPacket("Welcome".getBytes(), "Welcome"
                        .length(), dpreceive.getAddress(), 
4502);
                dsSend.send(dpsend);
                
if (map.size() % 3 == 0)
                    
while (it.hasNext()) {
                        String key 
= (String) it.next();
                        System.out.println(key 
+ "->" + map.get(key));
                    }

            }

        }
 catch (SocketException e) {
            e.printStackTrace();
        }
 catch (UnknownHostException e1) {
            e1.printStackTrace();
        }
 catch (IOException e) {
            e.printStackTrace();
        }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值