热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaUDP通信:JavaDatagramSocket类和DatagramPacket类

在TCPIP协议的传输层除了一个TCP协议之外,还有一个UDP协议。UDP协议是用户数据报协议的简称,也用于网络数据的传输。虽然UDP协议是一种不太可靠

在 TCP/IP 协议的传输层除了一个 TCP 协议之外,还有一个 UDP 协议。UDP 协议是用户数据报协议的简称,也用于网络数据的传输。虽然 UDP 协议是一种不太可靠的协议,但有时在需要较快地接收数据并且可以忍受较小错误的情况下,UDP 就会表现出更大的优势。

下面是在 Java 中使用 UDP 协议发送数据的步骤。

  1. 使用 DatagramSocket() 创建一个数据包套接字。
  2. 使用 DatagramPacket() 创建要发送的数据包。
  3. 使用 DatagramSocket 类的 send() 方法发送数据包。


接收 UDP 数据包的步骤如下:

  • 使用 DatagramSocket 创建数据包套接字,并将其绑定到指定的端口。
  • 使用 DatagramPacket 创建字节数组来接收数据包。
  • 使用 DatagramPacket 类的 receive() 方法接收 UDP 包。

DatagramPacket 类

java.net 包中的 DatagramPacket 类用来表示数据报包,数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。表 1 和表 2 简单介绍了 DatagramPacket 的构造方法和常用方法。
 

表1 DatagramPacket的构造方法
构造方法说明
DatagramPacket(byte[] buf,int length)构造 DatagramPacket,用来接收长度为 length 的数据包。
DatagramPacket(byte[] buf,int offset,
int length)
构造 DatagramPacket,用来接收长度为 length 的包,在缓
冲区中指定了偏移量。
DatagramPacket(byte[] buf,int length,
InetAddress address,int port)
构造 DatagramPacket,用来将长度为 length 的包发送到指
定主机上的指定端口。
DatagramPacket(byte[] buf,int length,
SocketAddress address)
构造数据报包,用来将长度为 length 的包发送到指定主机上
的指定端口。
DatagramPacket(byte[] buf,int offset,
int length,InetAddress address,int port)
构造 DatagramPacket,用来将长度为 length 偏移量为 offset
的包发送到指定主机上的指定端口。
DatagramPacket(byte[] buf,int offset,
int length,SocketAddress address)
构造数据报包,用来将长度为 length、偏移量为 offset 的包发
送到指定主机上的指定端口。

 

表2 DatagramPacket的常用方法
方法说明
InetAddress getAddress()返回某台机器的 IP 地址,此数据报将要发往该机器或者
从该机器接收。
byte[] getData()返回数据缓冲区。
int getLength()返回将要发送或者接收的数据的长度。
int getOffset()返回将要发送或者接收的数据的偏移量。
int getPort()返回某台远程主机的端口号,此数据报将要发往该主机或
者从该主机接收。
getSocketAddress()获取要将此包发送或者发出此数据报的远程主机的
SocketAddress(通常为 IP地址+端口号)。
void setAddress(InetAddress addr)设置要将此数据报发往的目的机器的IP地址。
void setData(byte[] buf)为此包设置数据缓冲区。
void setData(byte[] buf,int offset,
int length)
为此包设置数据缓冲区。
void setLength(int length)为此包设置长度。
void setPort(int port)设置要将此数据报发往的远程主机的端口号。
void setSocketAddress(SocketAddress
address)
设置要将此数据报发往的远程主机的
SocketAddress(通常为 IP地址+端口号)。

DatagramSocket 类

DatagramSocket 类用于表示发送和接收数据报包的套接字。数据报包套接字是包投递服务的发送或接收点。每个在数据报包套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。

DatagramSocket 类的常用构造方法如表 3 所示。
 

表3 DatagramSocket 的构造方法
构造方法说明
DatagramSocket()构造数据报包套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket(int port)创建数据报包套接字并将其绑定到本地主机上的指定端口。
DatagramSocket(int portJnetAddress addr)创建数据报包套接字,将其绑定到指定的本地地址。
DatagramSocket(SocketAddress bindaddr)创建数据报包套接字,将其绑定到指定的本地套接字地址。


DatagramSocket 类的常用方法如表 4 所示。
 

表4 DatagramSocket 的常用方法
方法说明
void bind(SocketAddress addr)将此 DatagramSocket 绑定到特定的地址和端口。
void close()关闭此数据报包套接字。
void connect(InetAddress address,int port)将套接字连接到此套接字的远程地址。
void connect(SocketAddress addr)将此套接子连接到远程套接子地址(IP地址+端口号)。
void disconnect()断开套接字的连接。
InetAddress getInetAddress()返回此套接字连接的地址。
InetAddress getLocalAddress()获取套接字绑定的本地地址。
int getLocalPort()返回此套接字绑定的本地主机上的端口号。
int getPort()返回此套接字的端口。

例 1

编写 UDP 程序,要求客户端程序可以向服务器端发送多条数据,服务器端程序可以接收客户端发送的多条数据并将其信息输出在控制台,主要步骤如下所示。

(1) 创建一个类作为客户端,在 main() 方法定义一个 DatagramSocket 对象和一个 DatagramPacket 对象并初始化为 null。然后再定义一个 InetAddress 对象和一个端口号并分别进行初始化,代码如下所示。


  1. public static void main(String[] args)
  2. {
  3. DatagramSocket ds=null;
  4. DatagramPacket dpSend=null;
  5. InetAddress ia=InetAddress.getByName("127.0.0.1");
  6. int port=3021;
  7. }


(2) 使用 DatagramSocket 的 send(DatagramPacket p) 方法向服务器端发送数据报包,使用循环的方式完成 5 次数据的发送,每发送 1 次数据线程休眠 1000 毫秒,数据发送完毕调用 close() 方法,关闭 DatagramSocket 对象,代码如下。


  1. try
  2. {
  3. ds=new DatagramSocket();
  4. for(int i&#61;0;i<5;i&#43;&#43;)
  5. {
  6. byte[] data&#61;("我是 UDP 客户端"&#43;i).getBytes();
  7. dpSend&#61;new DatagramPacket(data,data.length,ia,port);
  8. ds.send(dpSend);
  9. Thread.sleep(1000);
  10. }
  11. ds.close();
  12. }
  13. catch(IOException | InterruptedException e)
  14. {
  15. // TODO 自动生成的 catch 块
  16. e.printStackTrace();
  17. }


(3) 创建一个类作为服务器端&#xff0c;在 main() 方法中定义一个 DatagramSocket 对象和一个 DatagramPacket 对象并初始化为 null&#xff0c;再定义一个端口号&#xff0c;代码如下所示。


  1. public static void main(String[] args)
  2. {
  3. DatagramSocket ds&#61;null;
  4. DatagramPacket dpReceive&#61;null;
  5. int port&#61;3021;
  6. }


(4) 如果成功连接到 UDP 服务器则输出“UDP 服务器已启动。。。”。循环接收客户端发送的数据&#xff0c;并将其发送的内容以及IP地址等信息输出到控制台&#xff0c;代码如下所示。


  1. try
  2. {
  3. ds&#61;new DatagramSocket(port);
  4. System.out.println("UDP服务器已启动。。。");
  5. byte[] b&#61;new byte[1024];
  6. while(ds.isClosed()&#61;&#61;false)
  7. {
  8. dpReceive&#61;new DatagramPacket(b, b.length);
  9. try
  10. {
  11. ds.receive(dpReceive);
  12. byte[] Data&#61;dpReceive.getData();
  13. int len&#61;Data.length;
  14. System.out.println("UDP客户端发送的内容是&#xff1a;" &#43; new String(Data, 0, len).trim());
  15. System.out.println("UDP客户端IP&#xff1a;" &#43; dpReceive.getAddress());
  16. System.out.println("UDP客户端端口&#xff1a;" &#43; dpReceive.getPort());
  17. }
  18. catch(IOException e)
  19. {
  20. e.printStackTrace();
  21. }
  22. }
  23. }
  24. catch(SocketException e1)
  25. {
  26. // TODO 自动生成的 catch 块
  27. e1.printStackTrace();
  28. }
  29. }


(5) 最后关闭 DatagramSocket 对象。执行服务器端程序&#xff0c;运行结果如下所示。

UDP服务器已启动。。。


(6) 再运行客户端程序&#xff0c;控制台的输出结果如下所示。

UDP客户端发送的内容是&#xff1a;我是UDP客户端0
UDP客户端IP&#xff1a;/127.0.0.1
UDP客户端端口&#xff1a;53472
UDP客户端发送的内容是&#xff1a;我是UDP客户端1
UDP客户端IP&#xff1a;/127.0.0.1
UDP客户端端口&#xff1a;53472
UDP客户端发送的内容是&#xff1a;我是UDP客户端2
UDP客户端IP&#xff1a;/127.0.0.1
UDP客户端端口&#xff1a;53472
UDP客户端发送的内容是&#xff1a;我是UDP客户端3
UDP客户端IP&#xff1a;/127.0.0.1
UDP客户端端口&#xff1a;53472
UDP客户端发送的内容是&#xff1a;我是UDP客户端4
UDP客户端IP&#xff1a;/127.0.0.1
UDP客户端端口&#xff1a;53472


推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
author-avatar
羽书uv吧
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有