java网络之基于UDP的聊天程序示例解析

下面是关于 "java网络之基于UDP的聊天程序示例解析" 的完整攻略:

一、背景介绍

Java编程过程中,网络编程是非常重要的一部分。UDP协议是Java中常用的一种协议,其具有数据传输快、连接简单等特点,非常适合一些及时性要求不高的网络应用,比如聊天室程序等。本篇攻略就是针对基于UDP协议的聊天程序的编写,进行详细的解析。

二、程序设计思路

本程序的设计思路可以归纳为如下几个步骤:

  1. 客户端与服务器端都使用UDP协议进行数据的传输与接收。
  2. 客户端之间的通信需要通过服务器进行转发。
  3. 客户端与服务器之间,以及客户端之间,都需要确立好唯一的通讯对象,以进行数据的传输。
  4. 对于向服务器端发送的数据,需要使用线程池进行优化。

三、程序示例解析

示例1:服务器端代码

public class ChatServer {
    // 维护所有在线的客户端
    private static Map<String, SocketAddress> onlineClients = new ConcurrentHashMap<String, SocketAddress>();

    public static void main(String[] args) throws Exception {
        // 创建DatagramSocket,监听1024端口
        DatagramSocket server = new DatagramSocket(1024);
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        System.out.println("服务器已启动!");
        while (true) {
            // 接收客户端发来的消息
            server.receive(packet);
            // 解析收到的消息
            String message = new String(packet.getData(), 0, packet.getLength(), "UTF-8");
            String[] arr = message.split(":");
            if (arr.length == 2) {
                // 收到客户端的上线请求
                String name = arr[1];
                onlineClients.put(name, packet.getSocketAddress());
                // 向该客户端反馈上线成功的消息
                String msg = "sys: welcome " + name + " online!";
                byte[] responseBuf = msg.getBytes("UTF-8");
                DatagramPacket responsePacket = new DatagramPacket(responseBuf, responseBuf.length, packet.getAddress(), packet.getPort());
                server.send(responsePacket);
            } else if (arr.length == 3) {
                // 收到客户端的消息,请求转发到指定客户端
                String from = arr[0];
                String to = arr[1];
                String content = arr[2];
                SocketAddress toAddress = onlineClients.get(to);
                String msg = from + ":" + content;
                byte[] responseBuf = msg.getBytes("UTF-8");
                DatagramPacket responsePacket = new DatagramPacket(responseBuf, responseBuf.length, toAddress);
                server.send(responsePacket);
            }
        }
    }
}

以上是服务器端的主要代码逻辑,主要实现了接收客户端消息,处理客户端上下线请求,转发消息等功能。

示例2:客户端代码

public class ChatClient {
    private static String name;
    private static SocketAddress serverAddress;
    private static DatagramSocket client;
    private static ExecutorService threadPool = Executors.newSingleThreadExecutor();

    public static void main(String[] args) throws Exception {
        // 设定服务器地址
        serverAddress = new InetSocketAddress("127.0.0.1", 1024);
        // 创建DatagramSocket
        client = new DatagramSocket();
        System.out.println("请输入你的名字:");
        Scanner scanner = new Scanner(System.in);
        name = scanner.nextLine();
        // 向服务器发送上线请求
        String message = "login:" + name;
        byte[] buf = message.getBytes("UTF-8");
        DatagramPacket packet = new DatagramPacket(buf, buf.length, serverAddress);
        client.send(packet);
        threadPool.execute(new ReceiveMessageTask());
        // 发送消息给其他在线客户端
        while (true) {
            String line = scanner.nextLine();
            if (StringUtils.isEmpty(line)) continue;
            String[] arr = line.split(":");
            if (arr.length == 2) {
                String to = arr[0];
                String content = arr[1];
                String message2 = name + ":" + to + ":" + content;
                byte[] buf2 = message2.getBytes("UTF-8");
                SocketAddress toAddress = onlineClients.get(to);
                if (toAddress != null) {
                    DatagramPacket packet2 = new DatagramPacket(buf2, buf2.length, toAddress);
                    client.send(packet2);
                } else {
                    System.out.println("用户 " + to + " 不在线");
                }
            } else {
                System.out.println("格式不正确,正确格式为:[对方用户名]:[消息内容]");
            }
        }
    }

    static class ReceiveMessageTask implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    byte[] buf = new byte[1024];
                    DatagramPacket packet = new DatagramPacket(buf, buf.length);
                    client.receive(packet);
                    String message = new String(packet.getData(), 0, packet.getLength(), "UTF-8");
                    System.out.println(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

以上是客户端的主要代码逻辑,主要实现了登录请求的发送,消息的发送,消息的接收等功能。

四、总结

以上就是基于UDP协议的聊天程序示例解析的相关内容,通过本攻略的学习,读者可以了解基于UDP协议进行数据传输的流程和步骤,以及Java中的相关网络编程知识。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java网络之基于UDP的聊天程序示例解析 - Python技术站

(0)
上一篇 2023年5月30日
下一篇 2023年5月30日

相关文章

  • java开发之Jdbc分页源码详解

    首先,我们需要了解JDBC分页的概念,它可以帮助我们在处理大量数据时,避免一次性获取过多的数据,从而提高程序的性能。 下面是一个基于JDBC的分页实现的示例代码,供您参考: import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement;…

    Java 2023年6月16日
    00
  • 注意Java中 new BigDecimal(double val) 的使用

    使用 new BigDecimal(double val) 构造方法创建 BigDecimal 实例时,需要注意以下几点: 浮点数精度问题:由于浮点数的精度问题,当我们使用 new BigDecimal(double val) 构造方法创建 BigDecimal 实例时,可能会导致精度丢失。比如下面的代码段: java double d = 0.1; // …

    Java 2023年5月20日
    00
  • Java基础之文件和目录操作

    Java基础之文件和目录操作 在Java中,文件和目录操作是很常见的任务。Java提供了一系列的类和方法来实现这些操作。本文将介绍Java中文件和目录的基础操作。 文件基础操作 创建文件 在Java中,使用File类来创建文件。可以通过以下代码创建一个新的文件: File file = new File("example.txt"); t…

    Java 2023年6月1日
    00
  • BeanUtils.copyProperties使用总结以及注意事项说明

    BeanUtils.copyProperties使用总结以及注意事项说明 Java中的BeanUtils.copyProperties方法可以将一个Java Bean的属性值拷贝到另外一个Java Bean中。此方法的使用非常方便,本文将对其使用进行总结,并介绍一些注意事项。 方法签名 下面是BeanUtils.copyProperties方法的签名: vo…

    Java 2023年5月20日
    00
  • 如何使用BigDecimal实现Java开发商业计算

    如何使用BigDecimal实现Java开发商业计算 Java开发中涉及商业计算时,使用double或float计算往往会存在精度问题,因此使用BigDecimal类进行计算可以避免此类问题。下面我们详细讲解如何使用BigDecimal实现Java开发商业计算的完整攻略。 引入BigDecimal类 首先需要在代码中引入BigDecimal类。 import…

    Java 2023年5月26日
    00
  • 浅析java中的取整(/)和求余(%)

    浅析Java中的取整(/)和求余(%) 在Java中,取整运算符/和求余运算符%是常见的算术运算符。它们经常被用来处理整数类型的数据。然而,在使用这两个运算符时,很多人常常容易混淆它们的意义和区别。本文将对这两个运算符进行一些简单的分析,并通过一些示例来说明它们的具体用法。 取整运算符(/) 在Java中,取整运算符/通常被用来进行整数除法操作,它返回两个整…

    Java 2023年5月26日
    00
  • java自定义日期转化类示例

    当我们在Java中处理时间和日期相关的数据时,有时可能会需要自定义日期和时间的格式,或者需要将特定格式的日期和时间转换成标准的Java日期对象。为了实现这些功能,我们可以创建自定义日期转化类。 以下是创建Java自定义日期转化类的步骤: 步骤1:创建一个Java类,例如DateUtils,用于实现自定义日期转换方法。确保类名和文件名相同。 步骤2:导入Jav…

    Java 2023年5月20日
    00
  • Sprint Boot @Qualifier使用方法详解

    在Spring Boot中,@Qualifier注解用于指定依赖注入的具体实现类。本文将详细介绍@Qualifier注解的作用和使用方法,并提供两个示例。 @Qualifier注解的作用 在Spring Boot中,当存在多个实现类时,使用@Qualifier注解可以指定依赖注入的具体实现类。使用@Qualifier注解,可以避免依赖注入时出现歧义,确保注入…

    Java 2023年5月5日
    00
合作推广
合作推广
分享本页
返回顶部