JavaEE - 网络编程之回显服务器

目录

一.什么是回显服务器?

二.UDP是什么?

1.TCP 是有链接的, UDP 是无连接的

2.TCP是可靠传输的,UDP是不可靠传输的

3.TCP是面向字节流的,UDP是面向数据报

4.TCP和UDP是全双工的

三.UDP的 socket api 

四. 具体代码实现

1.服务器部分

2.客户端部分 

 3. 具体的流程到底是个啥?

4.执行结果


一.什么是回显服务器?

回显服务器是网络编程中一个简单的代码示例,回显的意思就是客户端发给服务器什么东西,服务器就返回给客户端什么东西。此处我们使用UDP来进行编写回显服务器。

既然此处我们要使用UDP来编写回显服务器,那么我们就有必要去了解UDP是什么?

二.UDP是什么?

UDP是五层网络模型中传输层的协议。其实这个传输层的协议有两个,一个是TCP,另一个就是UDP。两者的区别如下:

1.TCP 是有链接的, UDP 是无连接的

此处链接的本质就是建立连接的双方,各自保存对方的信息.

TCP要想通信,就需要先建立连接(保存对方信息),然后才能后续通信。

如果A 想和 B 建立连接,但是 B 拒绝了!通信就无法完成!

UDP要想建立链接,就直接发送数据即可,不需要征得对方的同意,UDP自身也不会保存对方信息。但是应用程序层面会知道。

2.TCP是可靠传输的,UDP是不可靠传输的

什么是可靠?究竟什么样子才算可靠?

其实这个可靠是一个模糊的概念,比如我是一个非常厉害的老中医,但是假如有病人问我这个病能不能百分百治好的时候,我只能说:“我尽力治好~~~” 。  此时我是可靠的呢还是不可靠的呢?其实应该是可靠的,因为此时我的医术很精明,已经很接近有百分百的把握了。

在网络上进行通信,A - >B 的过程中,这个消息是不可能 100% 送达的

TCP内置了可靠传输机制,发送失败的时候会采取一定的措施(比如尝试重传之类的)

UDP就没有内置可靠传输机制!

但是我们思考,为什么UDP不搞一个可靠传输呢?

因为可靠传输是要付出代价的: 机制更复杂    传输效率更低~

3.TCP是面向字节流的,UDP是面向数据报

TCP是以字节为单位来进行传输的.

UDP是以数据报为单位来进行传输的.

4.TCP和UDP是全双工的

也就是两者都允许双向通信,客户端可以发送请求给服务器,服务器也可以发送相应给客户端。

三.UDP的 socket api 

socket本质上就是一个特殊的文件,把“网卡”抽象成了文件

往socket 文件中写数据,就相当于通过网卡发送数据

往socket 文件中读数据,就相当于通过网卡接收数据

在Java中,UDP的API主要有两种:

DatagramSocket  和  DatagramPacket

其实这两个对象,可以这样理解:DatagramSocket  就相当于一个网关文件, 而 DatagramPacket就相当于穿梭在这个网关文件中的数据报。

也就是客户端要发送这个数据报给服务器 ,  服务器要把相应再以数据报的形式发给客户端。

四. 具体代码实现

1.服务器部分

package net;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {//创建一个DatagramSocket对象 这个就相当于一个网卡文件private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {//这样写就是手动指定端口socket = new DatagramSocket(port);//socket = new DatagramSocket();  这样写就是系统自动分配端口}public void start() throws IOException {System.out.println("服务器启动!");while (true) {//1. 读取请求并解析//这里首先要创建出数据报类型的对象//此处的requestPacket对象就是作为输出型参数进行传递DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);//在receive之后,requestPacket中已经存储好了二进制数据//但是要想显示出来,就需要把这个二进制转为字符串//此处意思就是从 0 到数据的最大长度String request = new String(requestPacket.getData(),0,requestPacket.getLength());//2.根据请求计算相应//由于是回显服务器,请求是啥样,相应就是啥样String response = process(request);//3.把响应写回到客户端中//此时搞一个响应对象,DatagramPacket,在这个里面构造刚才的数据,再返回//注意response.getBytes().length 和 response.length 是不一样的,// 一个是获取字节的长度,另一个是获取字符的长度。如果response全是英文字符串,那就没事。但是如有中文的话就可能会出现问题DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);//打印日志文件System.out.printf("[%s:%d] req=%s, resp=%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}private String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
}

代码解读:

1. 服务器要手动指定端口, socket = new DatagramSocket(port); 这样的目的就是让多个客户端能够精准访问。

2. process 方法就是一个简单的 传进去什么,返回什么东西。这个就是回显的体现。

3.DatagramSocket 有不同的版本 , 我们要根据需要 使用不同的参数.

        比如在服务器进行接收的时候,就需要先构造好一个空的DatagramSocket对象(相当于空盘子),然后放到recevie里面等待客户端发来东西。然后把客户端的东西放到这个对象中(放到盘子里)。

        比如在服务器进行回应的时候,此时的DatagramSocket里面就应该是response ,也就是根据这个response 字符串进行构造DatagramSocket对象。

4.requestPacket.getSocketAddress() 意思就是服务器回应的时候,需要知道是谁发来的。

2.客户端部分 

package net;import Inner.Inter;import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null; //先制定网关文件为空private String serverIp = "";private  int serverPort = 0; //端口号public UdpEchoClient(String ip,int port) throws SocketException {//客户端这边就是手动指定端口socket = new DatagramSocket();serverIp = ip;serverPort = port;}public void start() throws IOException {System.out.println("客户端启动!");Scanner scanner = new Scanner(System.in);while (true) {//1.从控制台读取数据,作为请求System.out.print("-> ");String request = scanner.next();//2.将请求内容构造成DatagramPacket数据报对象DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort);socket.send(requestPacket);//3.尝试读取服务器的相应DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);//4.把相应拼接成字符串并显示出来String response = new String(responsePacket.getData(),0, responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("172.0.0.1",9090);client.start();}
}

代码解读:

1. 客户端需要使用系统自动分配的端口。这是为什么呢?我们来想一下,加入我在我们大学开了一个窗口,那么我就是一个服务器,也就是给大家做饭的。各位同学们就是客户端。那么我的窗口位置就需要确定,以让同学们更好的找到我(也就是服务器的端口要手动指定)。那么各位同学在等待我做好饭的时候(等待服务器回应),所等待的位置是不是每次都相同?答案很明显:不是。 同学们等待我做饭的位置,是不定的!!!也就是可以理解为客户端的端口是随机的,是系统自动分配的

2. 知道需要分配端口号之后,客户端这边需要发送一个请求给服务器。那么这个请求需要构造成DatagramSocket 对象类型,才能够进行传输。

3.InetAddress.getByName(serverIp) 这个就是将服务IP 转化为数据报的形式,因为我们自己写的IP是字符串。

4. 客户端通过sent发送请求,然后receive等待相应。注意等待相应之前,应该先有一个空的DatagramSocket对象(空盘子)来接收这个相应!

 3. 具体的流程到底是个啥?

1). 首先服务器先启动。服务器启动之后,就会进入循环,执行到 receive 这里进行阻塞(因为客户端还没有发送请求过来);

2). 客户端也开始启动, 先进入while 循环 执行 scanner.next 并且也在这里阻塞. 直到用户输入一个内容

3). 客户端发送数据之后(服务器和客户端会同步执行)

     服务器: 就会从receive 中返回, 进一步的解析请求为字符串 , 指定 process方法, 执行sent 操作,执行打印操作.

     客户端:  继续往下执行,指定到客户端的 receive阻塞, 等待服务器的响应

4). 客户端收到从服务器返回的数据之后 , 就会从 receive 中停止阻塞并返回 . 然后执行打印操作

5). 服务器这边完成一次循环之后 , 又执行到了 receive这里

    客户端这边完成一次循环之后, 执行到了 scanner.next 这里

        双双进入阻塞, 如此再循环往复~~~~~

4.执行结果


总结: 写UDP版本的环回服务器 + 客户端的过程可以加深我们对于网络编程的细节概念。到这里我们就突破了次元壁,大家可以尝试在局域网内互相发送消息。只需要将服务器文件发送给另一台电脑并且执行,客户端这边改一下 IP 就可以了。大家可以尝试一下!

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

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

相关文章

C++ Primer Plus----第十二章--类和动态内存分布

本章内容包括:对类成员使用动态内存分配;隐式和显式复制构造函数;隐式和显式重载赋值运算符;在构造函数中使用new所必须完成的工作;使用静态类成员;将定位new运算符用于对象;使用指向对象的指针…

山西电力市场日前价格预测【2023-12-28】

日前价格预测 预测说明: 如上图所示,预测明日(2023-12-28)山西电力市场全天平均日前电价为814.30元/MWh。其中,最高日前电价为1500.00元/MWh,预计出现在08:00~08:45,17:00~20:15。最低日前电价为394.61元/…

AI人工智能大模型讲师叶梓《基于人工智能的内容生成(AIGC)理论与实践》培训提纲

【课程简介】 本课程介绍了chatGPT相关模型的具体案例实践,通过实操更好的掌握chatGPT的概念与应用场景,可以作为chatGPT领域学习者的入门到进阶级课程。 【课程时长】 1天(6小时/天) 【课程对象】 理工科本科及以上&#xff0…

elasticsearch 笔记二:搜索DSL 语法(搜索API、Query DSL)

文章目录 一、搜索 API1. 搜索 API 端点地址2. URI Search3. 查询结果说明5. 特殊的查询参数用法6. Request body Search6.1 query 元素定义查询6.2 指定返回哪些内容6.2.1 source filter 对_source 字段进行选择6.2.2 stored_fields 来指定返回哪些 stored 字段6.2.3 docValue…

经典文献阅读之--OccNeRF(基于神经辐射场的自监督多相机占用预测)

0. 简介 作为基于视觉感知的基本任务,3D占据预测重建了周围环境的3D结构。它为自动驾驶规划和导航提供了详细信息。然而,大多数现有方法严重依赖于激光雷达点云来生成占据地面真实性,而这在基于视觉的系统中是不可用的。之前我们介绍了《经典…

苹果Mac电脑甘特图管 EasyGantt最新 for mac

EasyGantt提供直观的界面,让用户能够轻松创建具有时间轴视图的甘特图。你可以添加并排列任务、设置任务的开始和结束日期、调整任务之间的依赖关系等。 任务管理:软件允许你添加、编辑和删除任务,设定任务的优先级和状态,并为每个…

Spring AOP<一>简介与基础使用

spring AOP 基础定义 含义使用切面组织多个Advice,Advice放在切面中定义。也就是说是定义通知的自定义类。自定义的AOP类Aspect连接点方法调用,异常抛出可以增强的点JoinPoint :也就是**被增强的方法的总称,可以获取具体方法的信息&#xff…

初识Sringboot3+vue3环境准备

环境准备 后端环境准备 下载JDK17https://www.oracle.com/java/technologies/downloads/#jdk17-windows 安装就下一步下一步,选择安装路径 配置环境 环境 JDK17、IDEA2021、maven3.5、vscode 后端 基础:javaSE,javaWeb、JDBC、SMM框架(Spr…

Unity JSON编码解码之LitJson 深度剖析

把LitJson的代码库放入到项目中,如图所示:JSON在游戏开发中是一种序列化/反序列化常用的技术,把游戏相关的数据,如地图组成,通过JSON编码,序列化成JSON文本,传输或存储, 要使用的时候再通过JSON技术把文本解析成数据对象&#xff…

竞赛保研 基于卷积神经网络的乳腺癌分类 深度学习 医学图像

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度,召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…

SSM驾校预约管理系统----计算机毕业设计

项目介绍 本项目分为管理员、教练、学员三种角色, 管理员角色包含以下功能: 学员管理、教练管理、车辆管理、关系管理、车辆维修管理、个人中心等功能。 教练角色包含以下功能: 我的课程、我的学员、车辆中心、个人中心等功能。 学员角色包…

跟着LearnOpenGL学习12--光照贴图

文章目录 一、前言二、漫反射贴图三、镜面光贴图3.1、采样镜面光贴图 一、前言 在跟着LearnOpenGL学习11–材质中,我们讨论了让每个物体都拥有自己独特的材质从而对光照做出不同的反应的方法。这样子能够很容易在一个光照的场景中给每个物体一个独特的外观&#xf…

【开源】基于JAVA语言的创意工坊双创管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员端2.2 Web 端2.3 移动端 三、系统展示四、核心代码4.1 查询项目4.2 移动端新增团队4.3 查询讲座4.4 讲座收藏4.5 小程序登录 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的创意工坊双创管理…

TwIST算法MALTLAB主程序详解

TwIST算法MALTLAB主程序详解 关于TwIST算法的具体原理可以参考: 链接: https://ieeexplore.ieee.org/abstract/document/4358846 链接: https://blog.csdn.net/jbb0523/article/details/52193209 该算法的MATLAB源代码: 链接: http://www.lx.it.pt/~bi…

wireshark access/trunk/hybrid报文分析

1,access接口 发送带vlan的报文 wireshark交换机配置 [Huawei-GigabitEthernet0/0/1] [Huawei-GigabitEthernet0/0/1]port link-type access [Huawei-GigabitEthernet0/0/1]port default vlan 100 [Huawei-GigabitEthernet0/0/2]port link-type access [Huawei-Gig…

【HarmonyOS】鸿蒙开发简介与项目基础配置演示

从今天开始,博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”,对于刚接触这项技术的小伙伴在学习鸿蒙开发之前,有必要先了解一下鸿蒙,从你的角度来讲,你认为什么是鸿蒙呢?它出现的意义又是…

Elasticsearch:升级索引以使用 ELSER 最新的模型

在此 notebook 中,我们将看到有关如何使用 Reindex API 将索引升级到 ELSER 模型 .elser_model_2 的示例。 注意:或者,你也可以通过 update_by_query 来更新索引以使用 ELSER。 在本笔记本中,我们将看到使用 Reindex API 的示例。…

MR实战:实现数据去重

文章目录 一、实战概述二、提出任务三、完成任务(一)准备数据文件1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录 (二)实现步骤1、Map阶段实现(1)创建Maven项目(2)添加相关依赖…

命令模式-实例使用

未使用命令模式的UML 使用命令模式后的UML public abstract class Command {public abstract void execute(); }public class Invoker {private Command command;/*** 为功能键注入命令* param command*/public void setCommand(Command command) {this.command command;}/***…

k8s之陈述式资源管理

1.kubectl命令 kubectl version 查看k8s的版本 kubectl api-resources 查看所有api的资源对象的名称 kubectl cluster-info 查看k8s的集群信息 kubectl get cs 查看master节点的状态 kubectl get pod 查看默认命名空间内的pod的信息 kubectl get ns 查看当前集群所有的命…