【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

目录
相关文章
|
11月前
|
存储 运维 数据挖掘
服务器数据恢复—EqualLogic存储硬盘出现坏道的数据恢复案例
某品牌EqualLogic PS6100存储阵列上有一组由16块硬盘组建的raid5磁盘阵列。磁盘阵列上层划分多个大小不同的卷,存放虚拟机文件。 硬盘出现故障导致存储阵列不可用,需要恢复存储阵列中的数据。
|
11月前
|
存储 运维 Oracle
服务器数据恢复—存储硬盘指示灯亮黄灯,RAID5阵列崩溃的数据恢复案例
服务器存储数据恢复环境: 某单位一台某品牌DS5300存储,1个机头+4个扩展柜,50块的硬盘组建了两组RAID5阵列。一组raid5阵列有27块硬盘,存放Oracle数据库文件。存储系统上层一共划分了11个卷。 服务器存储故障: 存储设备上两个硬盘指示灯亮黄色。其中一组RAID5阵列崩溃,存储不可用,设备已经过保。
|
11月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
569 1
|
11月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
496 1
|
11月前
|
机器学习/深度学习 分布式计算 Java
Java与图神经网络:构建企业级知识图谱与智能推理系统
图神经网络(GNN)作为处理非欧几里得数据的前沿技术,正成为企业知识管理和智能推理的核心引擎。本文深入探讨如何在Java生态中构建基于GNN的知识图谱系统,涵盖从图数据建模、GNN模型集成、分布式图计算到实时推理的全流程。通过具体的代码实现和架构设计,展示如何将先进的图神经网络技术融入传统Java企业应用,为构建下一代智能决策系统提供完整解决方案。
856 0
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解
|
Java 大数据
如何在Java中进行网络编程:Socket与NIO
如何在Java中进行网络编程:Socket与NIO
|
Java API 网络安全
Java网络编程入门
Java网络编程入门
|
Java API 开发者
Java网络编程基础与Socket通信实战
Java网络编程基础与Socket通信实战
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解