UDP数据报网络编程(实现简单的回显服务器,客户端)

       回显服务器表示客户端发的是啥,服务器就返回啥,主要是为了熟悉UDP数据报网络编程的基本步骤

        对于程序的所有分析都写到了代码上

UDP回显服务器代码

package UdpEcho;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;/*** Created with IntelliJ IDEA.* Description:* User: wuyulin* Date: 2023-08-09* Time: 11:52*/
//UDP回显服务器,客户端发的是啥,服务器就返回啥
//通过UDP回显服务器的实现来简单熟悉创建服务器的API
//我们创建了DatagramSocket类的对象,但是在程序中没有调用close方法关闭该对象
//1.我们整个程序只实例化了一个DatagramSocket类的对象(socket)
//2.socket对象的生命周期非常长,是跟随整个程序的,此时就需要socket对象保持打开的状态
//3.socket对象->系统中的socket文件->文件描述符(进程的pcb(进程控制块)的属性),最主要的目标是为了释放文件描述符表中的文件描述符,才要关闭socket对象
//而进程结束,就把pcb回收,里面的文件描述符表自然也被销毁了
//当程序中有多个socket对象,socket对象的生命周期较短,需要频繁的创建和释放,一定要记得close
public class UdpEchoServer {//对于实现UDP服务器DatagramSocket是不可或缺的类//要通过DatagramSocket类的对象(网卡对象)来进行客户端与服务器之间的数据交换private DatagramSocket socket=null;//在实例化UDP回显服务器的时候就要实例化一个DatagramSocket对象(网卡对象)//对于服务器我们在实例化DatagramSocket对象时需要指明服务器的端口号,方便客户端寻找public UdpEchoServer(int port) throws SocketException {socket=new DatagramSocket(port);}//定义一个start方法来启动UDP回显服务器public void start() throws IOException {System.out.println("服务器启动");//服务器启动以后要一直去接收客户端传来的请求,并进行处理以及回应while (true){//服务器在启动以后要处理的三件核心环节//1.读取客户端传来的请求,并解析(客户端传来的请求是一个二进制数组,要根据实际情况解析为字符串或数字等等)//UDP服务器进行发送和接收的数据单位是UDP数据报(DatagramPacket)//DatagramPacket数据报类型有两个参数,当DatagramPacket类型的对象用于接收数据,就不需要提供ip地址和端口号(SocketAddress)DatagramPacket requestPacket=new DatagramPacket(new byte[4080],4080);//客户端传来的请求(数据报)就会存储到DatagramPacket类型的对象requestPacket中//receive方法自带阻塞等待,当服务器没有接受到客户端传来的请求时,在receive方法这里就会进入阻塞等待,直到客户端传来请求为止socket.receive(requestPacket);//2.根据请求,计算出响应(这个是在实际工作中我们最主要编写的逻辑)//由于回显服务器对数据的处理很简单(客户端发的是啥,服务器就返回啥)//所以我们将客户端发出的请求转换为字符串再把字符串传递给客户端即可String request=new String(requestPacket.getData(),0,requestPacket.getLength());String repose=handle(request);//3.把响应发送给客户端//发送的响应也是DatagramPacket(UDP数据报)类型//由于要将响应发送给客户端,所以需要知道客户端的ip地址和端口号(SocketAddress类型)//requestPacket(接收客户端传来的请求)中含有服务器和客户端的ip地址和端口号//可以通过getSocketAddress方法获得客户端的ip地址和端口号(SocketAddress类)DatagramPacket reponsePacket=new DatagramPacket(repose.getBytes(),repose.getBytes().length,requestPacket.getSocketAddress());socket.send(reponsePacket);//服务器就完成了接收数据,处理数据,发送数据的过程//记录日志,方便观察程序执行效果//requestPacket是客户端传给服务器的请求报,所以其中有客户端和服务器的ip地址和端口号//通过getAddress方法获得客户端的ip地址,getPort方法获得客户端的端口号System.out.printf("[%s,%d] request:%s repose:%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,repose);}}//对客户端传来的请求进行处理private String handle(String request){return request;}public static void main(String[] args) throws IOException {UdpEchoServer udpEchoServer=new UdpEchoServer(8080);udpEchoServer.start();}
}

UDP回显客户端的代码

package UdpEcho;import java.io.IOException;
import java.net.*;
import java.util.Scanner;/*** Created with IntelliJ IDEA.* Description:* User: wuyulin* Date: 2023-08-09* Time: 11:53*/
//UPD回显客户端
public class UdpEchoClient {private DatagramSocket socket=null;private String ipServer=null;   //用来存储用户提供的服务器ip地址private int portSever=0;    //用来存储用户提供的服务器端口号//在实例化客户端的时候需要用户提供服务器的ip地址和端口号,这样才知道该客户端要联系哪个服务器public UdpEchoClient(String ipServer,int portSever) throws SocketException {this.ipServer=ipServer;this.portSever=portSever;//因为客户端的端口号是有操作系统随机分配的,要是指定客户端的端口号可能会导致冲突//所以实例化DatagramSocket对象的时候不写参数,不指定端口号socket=new DatagramSocket();}//开启客户端public void start() throws IOException {Scanner scanner=new Scanner(System.in);System.out.println("客户端启动");//要不停的读取用户输入的请求,将请求发送给服务器,并接收服务器发送回来的响应while (true){System.out.print("请求->");String request=scanner.next();//根据用户输入的请求实例化DatagramPacket数据报(因为UDP类型网络编程数据传输的基本单位是DatagramPacket数据报)//由于要将客户端的请求发送给服务器,所以需要在DatagramPacket类中声明服务器的ip地址和端口号//通过InetAddress类调用静态方法getByName实例化InetAddress类型的对象,getByName方法可以叫做工厂方法DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(ipServer),portSever);//将用户的请求发送给客户端socket.send(requestPacket);//接收服务器返回的的回应DatagramPacket reposePacket=new DatagramPacket(new byte[4080],4080);socket.receive(reposePacket);//对回应的数据报进行解析String repose=new String(reposePacket.getData(),0,reposePacket.getLength());//输出解析后得到的回应System.out.println(repose);}}public static void main(String[] args) throws IOException {UdpEchoClient udpEchoClient=new UdpEchoClient("127.0.0.1",8080);udpEchoClient.start();}
}

当我们用idea实现了上面的代码后可以通过idea如何开启多个客户端(一个代码开启多个客户端运行)来检验多个客户端向服务器传送请求的运行情况

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/34787.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ClickHouse查看执行计划(EXPLAIN语法)

1.EXPLAIN 语法示例 EXPLAIN [AST | SYNTAX | QUERY TREE | PLAN | PIPELINE | ESTIMATE | TABLE OVERRIDE] [setting value, ...] [ SELECT ... | tableFunction(...) [COLUMNS (...)] [ORDER BY ...] [PARTITION BY ...] [PRIMARY KEY] [SAMPLE BY ...] [T…

途乐证券-最准确的KDJ改良指标?

KDJ目标是技术剖析的一种重要目标之一,它是利用随机目标(%R)发展而来的,是一种反映商场超买和超卖状况的买卖目标。KDJ目标由快线(K线)、慢线(D线)和随机值(J线&#xff…

RestTemplate HTTPS请求忽略SSL证书

问题描述 使用RestTemplate发送HTTPS请求的时候,出现了这样的一个问题: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification …

MySQL多表查询

1.创建student和score表 创建score表 2.为student表和score表增加记录 向student表插入记录的INSERT语句如下: 向score表插入记录的INSERT语句如下: 1.查询student表的所有记录 2.查询student表的第2条到4条记录 3.从student表查询所有学生的学号&#…

2023最新影视泛目录系统,苹果cms最新下载地址

影视泛目录系统是指一种集成了电影、电视剧、综艺节目、动漫等多种影视资源资源的系统,其目的是为用户提供一个方便快捷的影视资源检索、浏览、分享、评论的平台。该系统通过对影视资源进行分类、标签化、评分等方式,为用户提供更加精准的检索和推荐服务…

C#多线程学习 生产者和消费者

前面说过,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数。这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发…

mousedown拖拽功能(vue3+ts)

因为项目有rem适配,使用第三方插件无法处理适配问题,所有只能自己写拖拽功能了 拖拽一般都会想到按下,移动,放开,但是本人亲测,就在div绑定一个按下事件就行了(在事件里面写另外两个事件&#x…

爬虫ip池越大越好吗?

作为一名资深的程序员,今天我要给大家分享一些关于爬虫ip池的知识。关于ip代理池的问题,答案是肯定的,池子越大越好。下面跟我一起来盘点一下ip池大的好处吧! 1、提高稳定性 爬虫ip池越大,意味着拥有更多可用的爬虫ip…

「C/C++」C/C++搭建程序框架

✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C」C/C程序设计「Win」Windows程序设计「DSA」数据结构与算法「File」数据文件格式 目录 1. 分离职…

Flume原理剖析

一、介绍 Flume是一个高可用、高可靠,分布式的海量日志采集、聚合和传输的系统。Flume支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制&…

使用阿里云服务器搭建Discuz论坛网站教程基于CentOS系统

阿里云百科分享使用阿里云服务器建站教程,本文是搭建Discuz论坛,Discuz!是一款通用的社区论坛软件系统,它采用PHP和MySQL组合的基础架构,为您提供高效的论坛解决方案。本文介绍如何在CentOS 7操作系统的ECS实例上搭建Discuz! X3.4…

Nginx 安装与部署

文章和代码已经归档至【Github仓库:https://github.com/timerring/front-end-tutorial 】或者公众号【AIShareLab】回复 nginx 也可获取。 文章目录 虚拟机安装CentOS7.4Linux配置配置上网配置静态ip Nginx的安装版本区别备份克隆 安装编译安装报错解决 启动Nginx防…

topo 成绩排名

题目描述 每到考试后,学校都会发成绩表给每个学生,但是很多同学更关心的是自己在班级里的排名,可惜排名信息并没有公开。 小雯同学很想知道这次期末考试的全班排名情况,但是她的同学却不愿意告诉她自己的分数,只告诉她…

分布式 - 消息队列Kafka:Kafka生产者发送消息的方式

文章目录 1. Kafka 生产者2. kafaka 命令行操作3. kafka 生产者发送消息流程4. Kafka 生产者的创建5. Kafka 生产者发送消息1. 发送即忘记2. 同步发送3. 异步发送 6. Kafka 消息对象 ProducerRecord 1. Kafka 生产者 不管是把Kafka作为消息队列、消息总线还是数据存储平台&…

wpf控件上移下移,调整子集控件显示顺序

页面代码: <!-- 导出A2,自定义导出设置列,添加时间:2023-8-9 14:14:18,作者:whl; --><Window x:Class="WpfSnqkGasAnalysis.WindowGasExportA2"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http:/…

git远程仓库的创建及使用

1.仓库的概念&#xff1a; 1.1 本地仓库&#xff1a; 了解远程仓库前我们先了解一下本地仓库&#xff0c;本地仓库开发人员在完成部分代码的编写之后&#xff0c;可以将这一部分的代码做一个提交。这个提交完全就是一个新的版本提交&#xff0c;当然这个提交动作是在开发者的电…

CSS革命:用Sass/SCSS引领前端创新

目录 前言SCSSSassSass 和 SCSS 的区别 前言 在现代的前端开发中&#xff0c;CSS已成为呈现网页和应用程序样式的核心。然而&#xff0c;原生的CSS语法在大型项目中可能变得混乱、冗长且难以维护。 为了解决这些问题&#xff0c;SCSS&#xff08;Sass CSS&#xff09;和Sass&am…

Java基础篇--数组

目录 声明和初始化数组&#xff1a; 访问和修改数组元素&#xff1a; 数组长度&#xff1a; 遍历数组&#xff1a; 多维数组的遍历&#xff1a; 数组的常见操作和方法&#xff1a; 拓展小知识&#xff1a; 数组是Java中的一种数据结构&#xff0c;用于存储相同类型的多个…

B100-技能提升-线程池分布式锁

目录 线程池什么是线程池&#xff1f;为什么用线程池?线程池原理常见四种线程池和自定义线程池 线程池 什么是线程池&#xff1f; 池化技术 为什么用线程池? 1 由于设置最大线程数&#xff0c;防止线程过多而导致系统崩溃。 2 线程复用&#xff0c;不需要频繁创建或销毁…

包管理机制pip3

pip3 安装pip3 安装pip3 apt install python3-pip yum install python3-pip从仓库出发的命令 查询仓库信息 // 获取默认pip3源 pip3 config get global.index-url查询所有软件包 查询已经安装的所有软件包 pip3 list从软件包出发的命令 从软件包名出发查询其他信息 查询…