Java Socket编程实例(五)- NIO UDP实践

介绍

本文是“Java Socket编程实例”系列的第五篇,将介绍Java NIO中的UDP(User Datagram Protocol)实践。UDP是一种面向无连接的协议,常用于高速传输数据、广播和流媒体等场景。相比于TCP,UDP的特点是传输速度快、没有连接建立和断开的过程,但是可靠性差,无法保证数据传输的顺序和正确性。

在本文中,我们将使用Java NIO中的DatagramChannel和Selector实现UDP的发送和接收,并实现一个简单的聊天程序。

UDP发送

DatagramChannel是Java NIO中专门用于UDP的通道,在使用前需要先打开通道。通道打开后,可以创建DatagramPacket(要发送的数据包)和SocketAddress(目标地址),将数据包发送给目标地址。

下面是一个简单的UDP发送示例:

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class UdpSender {
    public static void main(String[] args) throws Exception {
        DatagramChannel channel = DatagramChannel.open();
        String message = "Hello, UDP!";
        ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
        InetSocketAddress address = new InetSocketAddress("localhost", 8888);
        channel.send(buffer, address);
        channel.close();
    }
}

上面代码中,我们打开一个DatagramChannel,创建一个ByteBuffer,包装要发送的消息,创建要发送的SocketAddress,将数据包发送给目标地址。

注意,DatagramChannel中的send方法是非阻塞的,如果目标地址不可用,则立即返回IOException。如果需要进行重试或者报错处理,需要通过try-catch块捕获IOException并进行处理。

UDP接收

同样地,DatagramChannel也可以用来接收UDP数据包。接收数据包需要用到Selector进行多路复用,使用Selector监听DatagramChannel的可读事件,当有事件发生时处理数据包。

下面是UDP接收的示例:

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey;

public class UdpReceiver {
    public static void main(String[] args) throws Exception {
        DatagramChannel channel = DatagramChannel.open();
        channel.bind(new InetSocketAddress(8888));
        channel.configureBlocking(false);
        Selector selector = Selector.open();
        channel.register(selector, SelectionKey.OP_READ);
        while (true) {
            selector.select();
            for (SelectionKey key : selector.selectedKeys()) {
                if (key.isReadable()) {
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    InetSocketAddress address = (InetSocketAddress) channel.receive(buffer);
                    if (address != null) {
                        buffer.flip();
                        String message = new String(buffer.array(), 0, buffer.limit());
                        System.out.println(address + ": " + message);
                    }
                }
            }
        }
    }
}

上面的代码块中,我们首先打开一个DatagramChannel,并绑定端口号。绑定端口号之后需要将通道设置为非阻塞模式,并将通道注册到Selector中并监听可读事件。

在while循环中,使用Selector.select()等待事件的发生。当可读事件发生时,使用DatagramChannel的receive方法接收数据包,并将数据包中的数据读入到ByteBuffer的缓冲区中。读取完数据之后,我们需要将Buffer切换到读模式,解析缓冲区中的消息内容,然后进行下一步的操作。

异步定时器

我们可以使用Java NIO自带的异步定时器来控制发送和接收消息的时间。

下面是定时器的示例:

import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey;

public class UdpTimer {
    public static void main(String[] args) throws Exception {
        DatagramChannel channel = DatagramChannel.open();
        channel.bind(null);
        channel.configureBlocking(false);
        Selector selector = Selector.open();
        SelectionKey writeKey = channel.register(selector, SelectionKey.OP_WRITE);
        SelectionKey readKey = channel.register(selector, SelectionKey.OP_READ);
        ByteBuffer buffer = ByteBuffer.wrap("Ping".getBytes());
        while (true) {
            int readyChannels = selector.select();
            if (readyChannels == 0) continue;
            for (SelectionKey key : selector.selectedKeys()) {
                if (key.isWritable()) {
                    channel.send(buffer, readKey.attachment());
                    writeKey.interestOps(0);
                    readKey.interestOps(SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    ByteBuffer response = ByteBuffer.allocate(1024);
                    channel.receive(response);
                    System.out.println(new String(response.array(), 0, response.limit()));
                    readKey.interestOps(0);
                    writeKey.interestOps(SelectionKey.OP_WRITE);
                }
            }
        }
    }
}

在上面的代码中,我们首先创建一个无需绑定端口号的DatagramChannel,创建一个ByteBuffer,并将ByteBuffer中的数据填充为Ping请求。接着注册事件并等待事件发生。如果事件发生了,则进入while循环并根据事件类型进行相应的处理。

当写事件发生时,该程序发送Ping请求并关闭写事件监控,开始等待读事件发生。当读事件发生时,该程序从DatagramChannel中读取并解析回应,并关闭读事件监控,重新开始监控写事件。

使用以上方法可以实现UDP的异步通信。

总结

本文介绍了Java NIO中UDP的基本使用。通过使用DatagramChannel和Selector,我们可以实现UDP的发送和接收,并实现一个简单的聊天程序。此外,本文还介绍了Java NIO自带的异步定时器,可以用来控制发送和接收消息的时间。

阅读剩余 63%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java Socket编程实例(五)- NIO UDP实践 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 流放之路3.3游侠锐眼元素打击BD介绍 刷图攻坚开荒BD攻略

    流放之路3.3游侠锐眼元素打击BD介绍 简介 在流放之路3.3版本中,游侠职业的锐眼元素打击(Elemental Hit)建议是一种强大的刷图攻坚开荒BD(Build)。该BD利用游侠职业的高爆发伤害和元素伤害加成,能够快速清理地图并击败强大的敌人。 技能配置 以下是游侠锐眼元素打击BD的技能配置建议: 主技能:锐眼元素打击(Elemental Hit)- …

    other 2023年8月5日
    00
  • idea maven依赖引入失效无法正常导入依赖问题的解决方法

    解决 Maven 依赖引入失效无法正常导入依赖问题的攻略 当使用 Maven 构建项目时,有时候会遇到依赖引入失效的问题,导致无法正常导入依赖。下面是解决这个问题的完整攻略,包含了两个示例说明。 步骤一:清理本地 Maven 仓库 有时候,本地 Maven 仓库中的依赖可能出现问题,导致无法正确引入。因此,首先尝试清理本地 Maven 仓库,然后重新构建项目…

    other 2023年8月3日
    00
  • 电脑重视自动重启关机该怎么查找原因?

    电脑自动重启或关机的原因可能有很多种,例如操作系统的错误、硬件故障,甚至是电源问题。如果电脑出现了这种情况,我们应该先了解问题的原因,然后才能采取正确的措施去解决它。 以下是检查电脑自动重启或关机问题的完整攻略: 第一步:检查系统事件日志 打开“事件查看器”。 在左侧面板中,依次展开“Windows日志”→“系统”。 在右侧面板中,会显示所有系统事件的列表。…

    other 2023年6月27日
    00
  • 关于Java继承中父类和子类构造函数的问题

    关于Java继承中父类和子类构造函数的问题,可以从以下几个方面入手: 1. 构造函数的继承 继承是Java面向对象编程中一个很重要的概念,当子类继承一个父类时,它将会继承父类的所有字段和方法。但是,在Java中,子类并不会继承父类的构造函数,而是通过调用父类的构造函数,来完成子类对象的初始化。 子类调用父类构造函数的方法: public class Pare…

    other 2023年6月26日
    00
  • 使用top命令分析linux系统性能的详解

    使用top命令分析linux系统性能的详解 在Linux系统中,top是最常用的性能监控命令之一。它可以实时显示系统资源的使用情况,包括CPU、内存、进程等。下面是使用top命令分析Linux系统性能的详解。 使用top命令 在Linux系统中,可以通过以下命令打开top: top 或者 top -d <秒数> 其中,-d参数指定top命令的更新…

    other 2023年6月27日
    00
  • 电脑cpu温度多少正常

    电脑CPU温度多少正常? CPU温度标准区间 电脑CPU的温度通常介于30°C至80°C之间,不同的CPU型号、CPU负载以及CPU散热配置等因素会影响CPU的运行温度。因此,我们需要了解不同的CPU型号所对应的标准温度范围,才能够知道自己的电脑CPU是否正常工作。 CPU温度监控工具 为了准确的监控电脑CPU的温度,我们需要借助一些CPU温度监控软件,例如…

    其他 2023年4月16日
    00
  • Bootstrap入门书籍之(四)菜单、按钮及导航

    标题:Bootstrap入门书籍之(四)菜单、按钮及导航攻略 1. 菜单 在Bootstrap中,可以使用<ul>和<li>标签来创建导航菜单。以下是创建菜单的步骤: 在HTML文档中,创建一个<ul>元素,作为导航栏容器。 <ul class="nav"> <!– 菜单项 –&g…

    other 2023年6月28日
    00
  • ServerVariables集合检索预定的环境变量

    ServerVariables集合是ASP.NET中一个重要的内置变量集合,它包含所有可用的服务器端环境变量,包括用户信息、服务器信息、浏览器和客户端的信息等。我们可以通过检索ServerVariables集合中的键值对,获取一些预定义的环境变量。 检索 ServerVariables 集合预定环境变量的方法 以下是检索预定环境变量的步骤: 步骤 1 对于.…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部