转载请注明来源

目录

问题说明

这里给出两种解决方法

方法一:使用getLength()截取更新的数据部分。下图中,使用substring(0,p.getLength())截取了p.getData()中被更新的数据部分。

方法二:每次接收数据开始前,对DatagramPacket的数据进行置零。下图中,从第一次开始,都对DatagramPacket前getLength()个字节的数据进行置零。

总结

附测试代码


问题说明

DatagramPacket的两个方法getData()和getLength()是不对应的。getLength()反映了刚刚接收到的数据的长度,而getData()反映了DatagramPacket对应缓冲区中的新接收到的数据和未被覆盖的旧数据,当我们使用DatagramPacket来处理新接收到的数据时,就容易同时触及到旧数据导致混乱。下图所示,udp客户端Client A第一次收到了数据“welcome",getData()获得的数据是”welcome",getLength()的结果是7;ClientA第二次收到了数据“hi",getData()获得的数据是”hilcome",其保留了旧数据“welcome"未被覆盖的部分”lcome",而getLength()的结果是2,即“hi"的长度。

这里给出两种解决方法

方法一:使用getLength()截取更新的数据部分。下图中,使用substring(0,p.getLength())截取了p.getData()中被更新的数据部分。

方法二:每次接收数据开始前,对DatagramPacket的数据进行置零。下图中,从第一次开始,都对DatagramPacket前getLength()个字节的数据进行置零。

总结

方法一和方法二都能得到正确结果,但是方法二对缓冲区buf进行了直接操作,很容易发生数组元素访问越界的错误。在DatagramPacket 被receive时,缓冲区buf的length不变,DatagramPacket允许接收的最大字节数也不变;而getLength()的结果发生变化;新数据只是在缓冲区中从偏移量开始覆盖旧数据,如果旧数据长度更大,则保留部分旧数据。

建议使用方法一

附测试代码

package udp_test1.udp_client;//library
import java.io.*;
import java.net.*;
import java.util.Scanner;class Recv_Thread extends Thread{private byte [] buf;private DatagramSocket ds = null;private DatagramPacket p = null;public Recv_Thread(int buf_len, DatagramSocket ds) {buf = new byte[buf_len];this.ds = ds;p = new DatagramPacket(buf,250);}@Overridepublic void run() {while(true) {try {ds.receive(p);String str = new String(p.getData()).substring(0,p.getLength());System.out.println("来自["+p.getPort()+"]的数据:"+str);}catch(Exception e ) {e.printStackTrace();}}    }
}
class Send_Thread extends Thread{private DatagramSocket ds = null;private InetAddress des_address = null;private int des_port;Scanner s = new Scanner(System.in);Send_Thread(DatagramSocket ds, InetAddress des_address,int des_port){this.ds = ds;this.des_address = des_address;this.des_port = des_port;}@Overridepublic void run() {while(true) {        try {byte[] buf = s.nextLine().getBytes();DatagramPacket p = new DatagramPacket(buf,buf.length,des_address,des_port);ds.send(p);}catch(Exception e) {e.printStackTrace();}}}
}public class Udp_Client extends Thread{private DatagramSocket ds = null;private InetAddress des_address = null;private int des_port = 0;private int buf_len = 256;private Send_Thread st = null;private Recv_Thread rt = null;public Udp_Client(int src_port,int des_port, InetAddress des_address) {this.des_port = des_port;this.des_address = des_address;try{ds = new DatagramSocket(src_port);System.out.println("本地开启UDP "+src_port+" 端口");}catch(IOException e ) {e.printStackTrace();}}@Overridepublic void run() {try {st = new Send_Thread(ds,des_address,des_port);st.start();rt = new Recv_Thread(buf_len,ds);rt.start();    st.join();rt.join();}catch(Exception e) {e.printStackTrace();}ds.close();}
}

Java DatagramPacket 中的坑相关推荐

  1. java正则表达式中的坑String.matches(regex)、Pattern.matches(regex, str)和Matcher.matches()

    问题:程序会计算表达式的值 //将数值转换以K为单位 String value = "10*1000*1000"; String regex="\\s*\\*\\s*10 ...

  2. JAVA异常中的坑--trytry-catch-finally的执行顺序

    结论: 不管有没有出现异常,finally代码块都会执行: 不管try和catch的代码块中有return时,finally仍会执行,且如果finally代码块也有return,则此代码肯定会返回fi ...

  3. java专业编码_java编码中的坑(记一次解决编码BUG的经历) - 贪吃蛇学院-专业IT技术平台...

    1.2016年11月15日(周二),我被经理外派出差渝北金开大道,任务:解决那边的一个数据库乱码异常 2.那边的负责人描述:数据库原是utf8编码,他为了兼容emoji表情,改为utf8mb4,之后出 ...

  4. JDK中的坑:JDK中这些方法的bug你不要踩

    点击关注公众号,Java干货及时送达 图片来源:白夜追凶 前言: jdk作为我们每天必备的调用类库,里面大量提供了基础类供我们使用.可以说离开jdk,我们的java代码寸步难行,jdk带给我们的便利可 ...

  5. Java 8 中 Map 骚操作之 merge() 的用法

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | juejin.im/post/5d9b455a ...

  6. Java 语言中十大“坑爹”功能!

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源:https://www.sohu.com/a/35 ...

  7. Java web 开发填坑记 2 -如何正确的创建一个Java Web 项目

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72566261 本文出自[赵彦军的博客] Java web 开发填坑记 1-如何正确 ...

  8. 第91课:SparkStreaming基于Kafka Direct案例实战和内幕源码解密 java.lang.ClassNotFoundException 踩坑解决问题详细内幕版本

    第91课:SparkStreaming基于Kafka Direct案例实战和内幕源码解密    /* * *王家林老师授课http://weibo.com/ilovepains */  每天晚上20: ...

  9. 缓存详解-在java项目中使用缓存

    目录 一.概述 二.java常用的缓存 三.使用缓存将会面临的一些问题 穿透 雪崩 击穿 总结 三.缓存淘汰策略 缓存淘汰 在Spring项目中优雅的实现缓存 二级缓存推荐的实现 一.概述 在java ...

最新文章

  1. 场景法:基本流、备选流、构造场景
  2. 【Windows系统】基于vscode搭建go语言开发环境
  3. 50 xen虚拟化技术基础、xen虚拟化技术进阶
  4. Java中使用Observer接口和Observable类实践Observer观察者模式
  5. 不足补0 java_Java Android 开发数字不足位数前面补0
  6. github操作实用命令
  7. 小白spss学习笔记(一)
  8. ios下input框 数字键盘问题
  9. 如何恢复扩展属性为u的linux文件,chattr - 修改文件在Linux第二扩展文件系统(E2fs)上的特有属性...
  10. python sasl_python用sasl的方式连接ldap提示
  11. 关于录制短视频点播不能播放问题的总结
  12. JAVA入门-024(int的正负数)
  13. 三大运营商eSIM商用情况
  14. 计算机共享不了,电脑的共享开不了怎么办
  15. python一只青蛙一次可以_python算法题 python123网站单元四题目
  16. 高速PCB(五) 信号层覆铜选择困难症
  17. 华为OD德科面试+机试记录
  18. html图片浮动特效
  19. putty乱码问题及解决
  20. Unity性能优化之字体篇

热门文章

  1. 【已解决】ffmpy3.FFExecutableNotFoundError: Executable ‘ffmpeg‘ not found
  2. 【Linux】Linux进阶指令
  3. 火星人谚语系列之四:对问题最深入的认识是知道答案
  4. 算法应用-斐波那契数列
  5. Android 蓝牙开发(2)——低功耗蓝牙
  6. 525 Contiguous Array 连续数组
  7. Centos7的iso everything与DVD以及Live的区别
  8. StringUtils一些常用方法
  9. impala 使用记录
  10. Xcode引入了第三方的类库之后真机调试提示莫名其妙的错误