首页 > 编程语言 >Java 网络编程 —— 基于 UDP 的数据报和套接字

Java 网络编程 —— 基于 UDP 的数据报和套接字

时间:2023-06-11 17:23:47浏览次数:47  
标签:DatagramSocket UDP Java int DatagramChannel data 接字 数据 public

UDP 简介

UDP(User Datagram Protocol,用户数据报协议)是传输层的另一种协议,比 TCP 具有更快的传输速度,但是不可靠。UDP 发送的数据单元被称为 UDP 数据报,当网络传输 UDP 数据报时,无法保证数据报一定到达目的地,也无法保证各个数据报按发送的顺序到达目的地,例如:当发送方先发送包含字符串【hello】的数据报,再发送包含字符串【everyone】的数据报时,接收方有可能先接收到字符串【everyone】,再接收到字符串【hello】,也有可能什么数据也没有接收到,因为发送方发送的数据有可能在传输途中都被丢失了


DatagramPacket 类

DatagramPacket 表示数据报,它的构造方法可以被分为两种:

  • 创建用来接收数据的 DatagramPacket 对象
  • 创建用来发送数据的 DatagramPacket 对象

两种构造方法的主要区别是:

  • 用于发送数据的构造方法需要设定数据报到达的目的地的地址
  • 用于接收数据的构造方法无须设定地址

用于接收数据的构造方法包括:

//data:用来存放接收到的数据
//length:指定要接收的字节数
//offset:指定在data存放数据的起始位置,即data[offset],如果没有设定,那么初始位置为data[0]
public DatagramPacket(byte[] data, int length);
public DatagramPacket(bytel data, int offset, int length);

用于发送数据的构造方法包括:

//data:用来存放要发送的数据
//length:指定要发送的字节数
//offset:指定在data要发送数据的起始位置,即data[offset],如果没有设定,那么初始位置为data[0]
//address和port:来指定目的地的地址
public DatagramPacket(byte[] data, int offset, int length, InetAddress address, int port);
public DatagramPacket(byte[] data, int offset, int length, SocketAddress address);
public DatagramPacket(byte[] data, int length, InetAddress address, int port);
public DatagramPacket(byte[] data, int length, SocketAddress address);

DatagramPacket 类包括以下属性,提供了一系列 get/set 方法来获取或设置这些属性:

  • data:表示数据报的数据缓冲区
  • offset:表示数据报的数据缓冲区的起始位置
  • length: 表示数据报的长度
  • address:对于用于发送的数据报,address 属性表示数据报的目标地址。对于用于接收的数据报,address 属性表示发送者的地址
  • port:对于用于发送的数据报,port 属性表示数据报的目标 UDP 端口。对于用于接收的数据报,port 属性表示发送者的 UDP 端口

DatagramSocket 类

DatagramSocket 类负责接收和发送数据报,每个 DatagramSocket 对象都会与一个本地端口绑定,在此端口监听发送过来的数据报。在客户程序中,一般由操作系统为 DatagramSocket 类分配本地端口,这种端口也被称为匿名端口。在服务器程序中,一般由程序显式地为 DatagramSocket 类指定本地端口

DatagramSocket 的构造方法有以下几种重载形式:

//由操作系统分配的任意的可用端口
DatagramSocket();
//显式指定本地端口
DatagramSocket(int port);
//同时指定IP和端口
DatagramSocket(int port, InetAddress laddr);
DatagramSocket(SocketAddress bindaddr);

DatagramSocket 的 send 方法负责发送一个数据报,该方法的定义如下:

public void send(DatagramPacket dp) throws IOException

值得注意的是,UDP 提供不可靠的传输,如果数据报没有到达目的地,那么 send 方法不会抛出任何异常,发送方程序就无法知道数据报是否被接收方接收到,除非双方通过应用层的特定协议来确保接收方未收到数据报时,发送方能重发数据报

DatagramSocket 的 receive 方法负责接收一个数据报,该方法的定义如下:

public void receive(DatagramPacket datagramPacket) throws IOException

此方法从网络上接收一个数据报,如果网络上没有数据报,执行该方法的线程就会进入阻塞状态,直到收到数据报为止。参数 datagramPacket 用来存放接收到的数据报,如果接收的数据报太大,receive 方法会在 datagramPacket 的数据缓冲区内存放尽可能多的数据,其余的数据则丢弃

两个 TCP Socket 之间存在固定的连接关系,而一个 DatagramSocket 可以与其他任意一个 DatagramSocket 交换数据报。在某些场合,一个 DatagramSocket 可能只希望与固定的另一个远程 DatagramSocket 通信,从 JDK1.2 开始,DatagramSocket 添加了一些方法,利用这些方法,可以使一个 DatagramSocket 只能与另一个固定的 DatagramSocket 交换数据报

//该方法实际上不建立TCP意义上的连接,但能限制当前DataramSocket只对参数指定的远程主机和UDP端口收发数据报
public void connect(InetAddress host, int port);
//中止当前DatagramSocket已经建立的连接
public void disconnect();
//当且仅当DatagramSocket已经建立连接时返回所连接的远程UDP端口,否则返回“-1”
public int getPort();
//当且仅当DatagramSocket已经建立连接时返回所连接的远程主机的IP地址,否则返回null
public InetAddress getlnetAddress();
//当且仅当DatagramSocket已经建立连接时返回所连接的SocketAddress,否则返回null
public SocketAddress getRemoteSocketAddress();

DatagramSocket 的 close 方法会释放所占用的本地 UDP 端口,在程序中及时关闭不再需要的 DatagramSocket,这是好的编程习惯


DatagramChannel 类

DatagramChannel 是 SelectableChannel 的子类,可以被注册到一个 Selector。使用 DatagramChannel,可以使 UDP 服务器只需用单个线程就能同时与多个客户通信。DatagramChannel 在默认情况下采用阻塞模式,如果希望该为非阻塞模式,那么可以调用 configureBlocking(false) 方法

DatagramChannel 类的静态 open 方法返回一个 DatagramChannel 对象,每个 DatagramChannel 对象都关联了一个 DatagramSocket 对象,DatagramChannel 对象的 socket 方法返回这个 DatagramSocket 对象

DatagramChannel 对象被创建后,与它关联的 DatagramSocket 对象还没有被绑定到任何地址,必须调用 DatagramSocket 对象的 bind 方法来与一个本地地址绑定

DatagramChannel channel = DatagramChannel.open();
DataqramSocket socket = channel.socket();
SocketAddress address = new InetSocketAddress(8000);
socket.bind(address);

与 DatagramSocket 一样,DatagramChannel 的 connect(SocketAddress remote) 方法使得通道只能对特定的远程地址收发数据报

DatagramChannel 使用 send 方法发送数据

//把参数src的剩余数据作为一个数据报写到通道中,参数target指定目标地址,该方法返回发送的字节数
public int send(ByteBuffer src, SocketAddress target) throws IOException

DatagramChannel 使用 receive 方法从通道中读取一个数据报,存放在参数指定的 ByteBufer,并返回数据报的发送方的地址

public SocketAddress receive(ByteBuffer dst) throws IOException

如果 DatagramChannel 工作于阻塞模式,那么 receive 方法在读取到数据报之前不会返回。如果 DatagramChannel 工作于非阻寒模式,那么 receive 方法在没有数据报可读取的情况下立即返回 null

DatagramChannel 也可以使用 write 方法发送数据,与 send 方法区别在于:write 方法要求 DatagramChannel 已经建立连接

public int write(ByteBuffer src) throws IOException;
//依次发送ByteBuffer数组中每个ByteBuffer的数据
public long write(ByteBufferl] srcs) throws IOException;
//参数offse指定ByteBuffer数组的起始位置参数,length指定发送的ByteBuffer的数目
public long write(ByteBufferl] srcs, int offset, int length) throws IOException;

DatagramChannel 也可以使用 read 方法接收数据,同样的,它也要求 DatagramChannel 已经建立连接

public int read(ByteBuffer src) throws IOException;
//把数据报的数据保存到 ByteBuffer 数组中
public long read(ByteBuffer[l srcs) throws IOException;
public long read(ByteBuffer[] srcs, int offset, int length) throws IOException;

标签:DatagramSocket,UDP,Java,int,DatagramChannel,data,接字,数据,public
From: https://www.cnblogs.com/Yee-Q/p/17473218.html

相关文章

  • java多线程基础的学习
    java多线程学习(主要围绕着线程的实现、状态、同步、通信以及高级主题如线程池)1.线程、进程、多线程进程:正在进行中的程序,一个程序的执行过程,需要资源:内存、cpu。线程:属于进程,指的是一个可以独立运行的代码片段(执行单元、执行路径)。一个进程中有多个可以独立运行的执行单元,这......
  • Java 基础面试笔记(二)
    1.arraylist和linkedlist区别:概念上:ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。性能上: ArrayList 的查询效率比较高,增删动作的效率比较差,适用于查询比较频繁,增删动作较少的元素管理的集合。LinkedList 的查询效率低,但是增删效率很高。适用于增删动作的......
  • JAVA Set 交集,差集,并集
    /***Createdbyyuhuion2017/7/110011.*/importjava.util.HashSet;importjava.util.Set;publicclassTestSet{publicstaticvoidmain(String[]args){Set<String>result=newHashSet<String>();Set<String>......
  • Java8新特性Stream之list转map及问题解决
    List集合转Map,用到的是Stream中Collectors的toMap方法:Collectors.toMap具体用法实例如下://声明一个List集合Listlist=newArrayList();list.add(newPerson("1001","小A"));list.add(newPerson("1002","小B"));list.add(......
  • Java中匿名内部类
      packagecom.itheima.d8_innerclass_anonymous;/***目标:学习匿名内部类的形式和特点*/publicclassTest{publicstaticvoidmain(String[]args){Animala=newAnimal(){@Overridepublicvoidrun(){......
  • 一份55页Java性能调优PPT分享
    提起“肖桦”这个人,相信很多小伙伴对他比较陌生。除去现任唯品会资深技术专家头衔外,他更为技术圈所熟知的是他的著名开源项目:SpringSide。SpringSide是以springFramework为核心的,Pragmatic风格的JavaEE应用参考示例,是JavaEE世界中主流技术选型,最佳实践的总结与演示。到目前为......
  • java——微服务——spring cloud——Nacos——Nacos与Eureka区别
        ......
  • 【Java技术专题】「Guava开发指南」手把手教你如何进行使用Guava工具箱进行开发系统实
    异常传播有时候,您可能需要重新抛出捕获到的异常。这种情况通常发生在捕获到Error或RuntimeException时,因为您可能没有预料到这些异常,但在声明捕获Throwable和Exception时,它们也被包含在内了。为了解决这个问题,Guava提供了多种方法来判断异常类型并重新抛出异常。例如:try{......
  • java 聚合项目--pom.xml配置文件
    java聚合项目1.parent--pom.xml配置文件4.0.0<groupId>org.test.java.vip.train</groupId><artifactId>test-train-parent</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><modules>&l......
  • Java开发——Maven
    MVC模式MVC模式是软件工程中常见的一种软件架构模式,该模式把项目分为三个基本部分:模型Model、视图View和控制器Controller。视图:界面的显示,以及与用户的交互功能控制器:用来决定对于视图发来的请求需要那一个模型来处理,以及处理后需要跳回到哪一个视图,用来连接视图和模型模型:持......