java UDP 同步socket

前段时间使用Netty实现udp和多个无线wifi数据采集模块进行异步通信,结果发现丢包很严重,丢包率达到了百分之一,实在让人犯愁。领导说可能是底层代码出了问题,然后我使用java原生的udp进行同步通信,发现木有存在丢包问题。目前还不知道自己到底踩了什么坑,先记录于此,等哪天有空了再回来想想这个坑到底在哪。使用udp异步通信的客户端代码如下:       

public class UdpClient {
    public void run(String hostName,int port,Frame sendRecvFrame) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioDatagramChannel.class)
                    .option(ChannelOption.SO_BROADCAST, true)
                    .handler(new UdpClientHandler(sendRecvFrame));
            //绑定端口 若为0 可为任意端口 9990
            Channel ch = b.bind(UdpMThreadClient.srcPort).sync().channel();
            byte[] hexByte= HexUtil.hexStringToByte(sendRecvFrame.getSendFrame());
            //startTime
            UdpMThreadClient.startTime=System.currentTimeMillis();
            UdpMThreadClient.fileWriter.write(UdpMThreadClient.startTime+",");
            System.out.println("起始时间为:"+ UdpMThreadClient.startTime);
            ch.writeAndFlush(
                    new DatagramPacket(Unpooled.copiedBuffer(hexByte), new InetSocketAddress(
                                hostName, port))).sync();
            UdpMThreadClient.sendCommandCount++;
            if (!ch.closeFuture().await(1000)) {  //超时时间设置为1000ms
                UdpMThreadClient.errorReceiveCount++;
                System.out.println("等待超时");
                System.out.println("目前的误包数为:"+ UdpMThreadClient.errorReceiveCount);
                UdpMThreadClient.endTime=System.currentTimeMillis();
                UdpMThreadClient.fileWriter.write(sendRecvFrame.getSendFrame()+",");//发送数据
                UdpMThreadClient.fileWriter.write(UdpMThreadClient.endTime+",");//接收数据时间戳
                UdpMThreadClient.fileWriter.write("timeout"+",");//接收数据
                UdpMThreadClient.fileWriter.write(UdpMThreadClient.errorReceiveCount+",");//错误个数
                UdpMThreadClient.fileWriter.write(UdpMThreadClient.sendCommandCount+","); //发送总数
                UdpMThreadClient.fileWriter.write((UdpMThreadClient.endTime-UdpMThreadClient.startTime)+","); //响应时间
                UdpMThreadClient.fileWriter.write("2s\r\n"); //发送数据时间间隔
                UdpMThreadClient.fileWriter.flush();
            }
        } finally {
            group.shutdownGracefully();
        }
    }
这个主要的坑在于很多包会超时,将程序丢包结果截图如下:

使用PC和十个模块进行通信,结果每个udp通信都遭遇了大量的丢包。因此,再使用同步通信,测试一下。

udp同步通信的代码如下:

public class UdpClientSync {
      public static void main(String[] args){
          DatagramSocket sendSocket=null;
          long sendCommandCount=0;
          long errCount=0;
          long startTime=0;
          long endTime=0;
          long fileIndex=0;
          String textFilePath="E:/IdeaProjects/wirelesscom/data/";
          FileWriter fileWriter=UdpMThreadClient.createFileWriter(textFilePath, fileIndex);
          try{
              //创建发送方的套接字,IP默认为本地,端口号9990
              InetAddress srcInetAddress=InetAddress.getByName("192.168.1.127");
              int srcPort=9990;
              sendSocket=new DatagramSocket(srcPort,srcInetAddress);
              //确定要发送的数据
              String mes="01020000000555AA";
              byte[] buf= HexUtil.hexStringToByte(mes);
              InetAddress ip=InetAddress.getByName("192.168.1.150");
              //创建发送类型的数据报
              int port=6010;
              while(sendCommandCount<30000){
                  DatagramPacket sendPacket=new DatagramPacket(buf,buf.length,ip,port);
                  startTime=System.currentTimeMillis();
                  sendSocket.send(sendPacket);
                  sendCommandCount++;
                  byte[] getBuf=new byte[1024];
                  //创建接收型的数据报
                  DatagramPacket getPacket=new DatagramPacket(getBuf,getBuf.length);
                  //通过套接字接收数据
                  sendSocket.receive(getPacket);
                  endTime=System.currentTimeMillis();
                  //解析反馈的信息,并打印
                  byte[] responseByte = new byte[getPacket.getLength()];
                  System.arraycopy(getBuf,0,responseByte,0,getPacket.getLength());
                  String response= HexUtil.bytesToHexString(responseByte);
                  String originData="01020100A188";
                  if(response.equals(originData)) {
                      System.out.println("True:" + mes + ":" + response);
                  }else{
                      errCount++;
                      System.out.println("false:" + mes + ":" + response);
                  }
                  System.out.println("发送时间为:"+startTime);
                  System.out.println("接收时间为:"+endTime);
                  System.out.println("响应时间为:"+(endTime-startTime)+"ms");
                  System.out.println("误包数为:" + errCount + ",总数为:" + sendCommandCount);
                  fileWriter.write(startTime+",");//发送数据时间戳
                  fileWriter.write(mes+",");//发送数据
                  fileWriter.write(endTime+",");//接收数据时间戳
                  fileWriter.write( response+",");//接收数据
                  fileWriter.write(errCount+",");//错误个数
                  fileWriter.write(sendCommandCount+","); //发送总数
                  fileWriter.write((endTime-startTime)+","); //响应时间
                  fileWriter.write("1000\r\n"); //回车换行
                  fileWriter.flush();
                  long index=sendCommandCount/2000;
                  if(index>fileIndex){
                      fileIndex=index;
                      if(fileWriter!=null){
                          fileWriter.flush();
                          fileWriter.close();
                      }
                      fileWriter=UdpMThreadClient.createFileWriter(textFilePath, fileIndex);;
                  }
                  Thread.sleep(1000);
              }
          }catch(Exception e){
              e.printStackTrace();
          }finally{
              //关闭套接字
              if(sendSocket!=null){
                  sendSocket.close();
              }
          }

      }
}
结果发现并没有遇到错误,截图如下:

因为wifi采集模块自带服务端,所以一般不需要写服务端,为了方便以后自己对udp进行测试,特将udp服务端代码贴图如下:

public class UdpServerSync {
    public static void main(String[] args){
        DatagramSocket getSocket=null;
        try{
            //确定接收方的IP和端口号,IP地址为本地机器地址
            InetAddress ip=InetAddress.getByName("192.168.1.127");
            int port =10030;
            //创建接收方的套接字,并制定端口号和IP地址
            getSocket=new DatagramSocket(port,ip);
            while(true){
                byte[] buf=new byte[1024];
                DatagramPacket getPacket=new DatagramPacket(buf,buf.length);
                getSocket.receive(getPacket);
                //解析发送方传递的信息
                byte[] responseByte = new byte[getPacket.getLength()];
                System.arraycopy(buf,0,responseByte,0,getPacket.getLength());
                String response= HexUtil.bytesToHexString(responseByte);
                System.out.println("对方发送的信息:"+response);

                //通过数据报得到发送方的IP和端口号,并打印
                InetAddress sendIP=getPacket.getAddress();
                int sendPort=getPacket.getPort();
                System.out.println("对方的IP地址是:"+sendIP.getHostAddress());
                System.out.println("对方的端口号是:"+sendPort);

                //通过数据报得到发送方的套接字地址
                SocketAddress sendAddress=getPacket.getSocketAddress();
                String feedback="01010100A188";
                byte[] backBuf= HexUtil.hexStringToByte(feedback);
                //创建发送类型的数据报
                DatagramPacket sendPacket=new DatagramPacket(backBuf,backBuf.length,sendAddress);
                //通过套接字发送数据
                getSocket.send(sendPacket);
            }
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                 if(getSocket!=null){
                     getSocket.close();
                 }
            }


    }


      

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值