【Java 网络编程】UDP 服务器 与 客户端持续交互 案例

简介: 【Java 网络编程】UDP 服务器 与 客户端持续交互 案例

文章目录

I UDP 交互原理

II UDP 服务器端代码示例

III UDP 客户端代码示例

IV 服务器 客户端 运行结果



I UDP 交互原理


1. UDP 单播传输流程 : A 给 B 发送数据包 , B 设备一定要处于监听 X 端口状态 , A 向 B 的 X 端口发送数据包 , B 才能收到 ; B 收到 A 的数据包后 , B 就知道了 A 的端口号 Z 的信息了 , 此时 B 可以向 A 的 Z 端口号发送数据包 ;


2. 局域网设备交互 : A 设备给局域网其它设备发送信息 , 并能接收到其它设备回送给 A 的信息 ;


3. 接收信息设备监听 X 端口 : 此时 A 作为客户端时 , 服务器需要接收 A 发送的数据包 , 服务器需要监听一个指定的接口 X , 那么如果 A 发送广播消息 , 监听 X 端口的服务器就会收到 A 发送的消息 ;


4. A 提前监听端口 Z : 如果服务器在收到消息后立刻向 A 的 Z 端口回送一个反馈信息 , 设备 A 需要在发送消息之前就监听 Z 端口 , 才能实现上述功能 ;


5. 持续交互 : A 不断向其它设备的 X 端口发送信息 , 其它设备可以不断反馈信息给设备 A 的 Z 端口 , 这样就实现了客户端与服务器端数据交互的功能 ;




II UDP 服务器端代码示例


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.ArrayList;
public class UDPServer {
    public static void main(String[] args){
        System.out.println("服务器 开始运行");
        //开启接收数据的线程
        ReceiveThread receiveThread = new ReceiveThread();
        receiveThread.start();
    }
    /**
     * 服务器端监听客户端发送的信息
     */
    private static class ReceiveThread extends Thread{
        /**
         * 是否继续监听 , 循环控制变量
         */
        boolean isReceive = true;
        /**
         * 存储发送数据的客户端信息
         */
        ArrayList<Client> clients = new ArrayList<>();
        @Override
        public void run() {
            super.run();
            try {
                //I. 创建 DatagramSocket 对象 , 用于 UDP 数据包的发送和接收
                //1. UDP 数据包接收者 , 监听 8888 端口
                //      该 DatagramSocket 既可以接收数据包 , 也可以发送数据包
                DatagramSocket datagramSocket = new DatagramSocket(8888);
                //II. 接收 UDP 数据包 , 无限循环接收来自客户端的信息 , 并根据不同的信息进行不同处理
                while (isReceive){
                    //2. 接收数据包使用的缓冲区
                    byte[] receiveBuffer = new byte[256];
                    //3. 接收 UDP 数据包使用的 DatagramPacket 对象
                    DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
                    //4. 接收 UDP 数据包
                    datagramSocket.receive(receivePacket);
                    //5. 获取发送端的 IP 地址
                    String sendIP = receivePacket.getAddress().getHostAddress();
                    //6. 获取发送端的端口号
                    int sendPort = receivePacket.getPort();
                    //7. 获取接收到的数据的长度
                    int receiveLen = receivePacket.getLength();
                    //8. 获取接收到的数据 , 并转为字符串
                    String receiveData = new String(receivePacket.getData(), 0, receiveLen);
                    //9. 打印接收到的数据包信息
                    System.out.println("服务器 接收到 " + sendIP + " : " + sendPort + " 发送的数据 : " + receiveData);
                    //将客户端信息发送到
                    //III. 发送 UDP 数据包
                    //10. 将接收到的数据长度回送给发送者
                    String response = "服务器端 收到客户端发送的 " + receiveLen + " Byte 数据";
                    //11. 将字符串转为 byte[] 数组
                    byte[] responseData = response.getBytes();
                    //12. 创建发送数据包 , 需要传入的参数 1> 数据 2> 数据长度 3> 接收者的地址 4> 接收者的端口号
                    DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length,
                            receivePacket.getAddress(), receivePacket.getPort());
                    //13. 将数据包发送出去
                    datagramSocket.send(responsePacket);
                    System.out.println("服务器 向客户端 " + sendIP + " : " + sendPort + " 发送的数据 : " + response);
                    //退出服务器循环
                    if("exit".equals(receiveData)){
                        isReceive = false;
                    }
                }
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                System.out.println("服务器 运行结束");
            }
        }
    }
    /**
     * 封装向服务器端发送数据的客户端信息
     * 主要是保存客户端的 IP 地址和端口号
     */
    private static class Client{
        String ClientIP;
        String ClientPort;
        public Client(String clientIP, String clientPort) {
            ClientIP = clientIP;
            ClientPort = clientPort;
        }
    }
}



III UDP 客户端代码示例


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDPClient {
    public static void main(String[] args){
        try {
            System.out.println("客户端 开始运行");
            //I. 创建 DatagramSocket 对象 , 用于 UDP 数据包的发送和接收
            //1. UDP 数据包套接字 , 客户端 ,
            //      监听 8889 端口 , 发送和接收数据包都使用该端口
            DatagramSocket datagramSocket = new DatagramSocket(8889);
            //II. 人机交互控制台阻塞获取用户输入
            //1. 获取控制台输入流
            InputStream is = System.in;
            //2. 该输入流会阻塞 , 等待用户控制台输入
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            // 循环控制变量 , 循环发送和接收 UDP 数据包
            boolean flag = true;
            while(flag){
                //3. 阻塞命令行 , 等待用户输入一行数据, 并存入 string 对象中
                String string = br.readLine();
                //III. 向服务器发送 UDP 数据包
                //1. 将字符串转为 byte[] 数组
                byte[] sendData = string.getBytes();
                //2. 创建发送数据包 , 需要传入的参数 1> 数据 2> 数据长度 3> 接收者的地址 4> 接收者的端口号
                //      向服务器端发送数据 , 发送的端口是自动分配的
                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
                        InetAddress.getLocalHost(), 8888);
                //3. 将数据包发送出去
                datagramSocket.send(sendPacket);
                System.out.println("客户端 向服务器 : " +
                        InetAddress.getLocalHost() + " : " + 8888 + " 发送的数据 : " + string);
                //4. 退出
                if("exit".equals(string)){
                    flag = false;
                }
                //IV. 接收服务器反馈的 UDP 数据包
                //1. 接收数据包使用的缓冲区
                byte[] receiveBuffer = new byte[1024];
                //2. 接收 UDP 数据包使用的 DatagramPacket 对象
                DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
                //3. 接收 UDP 数据包
                datagramSocket.receive(receivePacket);
                //4. 获取发送端的 IP 地址
                String sendIP = receivePacket.getAddress().getHostAddress();
                //5. 获取发送端的端口号
                int sendPort = receivePacket.getPort();
                //6. 获取接收到的数据的长度
                int receiveLen = receivePacket.getLength();
                //7. 获取接收到的数据 , 并转为字符串
                String receiveData = new String(receivePacket.getData(), 0, receiveLen);
                //8. 打印接收到的数据包信息
                System.out.println("客户端 接收到服务器端反馈信息 : " +
                        sendIP + " : " + sendPort + " 发送的数据 : " + receiveData);
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("客户端 运行结束");
        }
    }
}





IV 服务器 客户端 运行结果


先运行服务器端 , 再运行客户端 ;


image.png

目录
相关文章
|
存储 弹性计算 网络协议
阿里云服务器ECS实例规格族是什么?不同规格CPU型号、处理器主频及网络性能参数均不同
阿里云ECS实例规格族是指具有不同性能特点和适用场景的实例类型集合。不同规格族如计算型c9i、通用算力型u1、经济型e等,在CPU型号、主频、网络性能、云盘IOPS等方面存在差异。即使CPU和内存配置相同,性能参数和价格也各不相同,适用于不同业务需求。
849 144
|
存储 运维 API
HPE OneView 10.0 - HPE 服务器、存储和网络设备集中管理软件
HPE OneView 10.0 - HPE 服务器、存储和网络设备集中管理软件
309 1
|
JSON 监控 API
在线网络PING接口检测服务器连通状态免费API教程
接口盒子提供免费PING检测API,可测试域名或IP的连通性与响应速度,支持指定地域节点,适用于服务器运维和网络监控。
2212 0
|
机器学习/深度学习 存储 监控
内部文件审计:企业文件服务器审计对网络安全提升有哪些帮助?
企业文件服务器审计是保障信息安全、确保合规的关键措施。DataSecurity Plus 是由卓豪ManageEngine推出的审计工具,提供全面的文件访问监控、实时异常告警、用户行为分析及合规报告生成功能,助力企业防范数据泄露风险,满足GDPR、等保等多项合规要求,为企业的稳健发展保驾护航。
419 0
|
11月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
533 1
|
11月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
468 1
|
人工智能 Java API
MCP客户端调用看这一篇就够了(Java版)
本文详细介绍了MCP(Model Context Protocol)客户端的开发方法,包括在没有MCP时的痛点、MCP的作用以及如何通过Spring-AI框架和原生SDK调用MCP服务。文章首先分析了MCP协议的必要性,接着分别讲解了Spring-AI框架和自研SDK的使用方式,涵盖配置LLM接口、工具注入、动态封装工具等步骤,并提供了代码示例。此外,还记录了开发过程中遇到的问题及解决办法,如版本冲突、服务连接超时等。最后,文章探讨了框架与原生SDK的选择,认为框架适合快速构建应用,而原生SDK更适合平台级开发,强调了两者结合使用的价值。
14712 33
MCP客户端调用看这一篇就够了(Java版)
|
存储 监控 Linux
Dell OpenManage Enterprise 4.5 - Dell 服务器、存储和网络设备集中管理软件
Dell OpenManage Enterprise 4.5 - Dell 服务器、存储和网络设备集中管理软件
346 0
|
存储 安全 Linux
Dell OpenManage Enterprise 4.4 - Dell 服务器、存储和网络设备集中管理软件
Dell OpenManage Enterprise 4.4 - Dell 服务器、存储和网络设备集中管理软件
499 4
Dell OpenManage Enterprise 4.4 - Dell 服务器、存储和网络设备集中管理软件

热门文章

最新文章