当前位置: 首页 > news >正文

[JavaEE] 网络编程----UDP / TCP 回显服务器

Author:MTingle
major:人工智能

---------------------------------------

Build your hopes like a tower!

文章目录

文章目录

一.客户端VS服务器

二.TCP / UDP 特点

三.UDP 回显服务器

UDP 服务器

UDP 客户端

UDP字典

四.TCP 回显服务器

TCP 服务器

TCP 客户端




一.客户端VS服务器

在网络中,主动发起通信的一方称为"客户端",被动接受的这一方,称为"服务器".同一个程序在不同场景中,可以是客户端,也可能是服务器.客户端给服务器发送的数据,称为"请求"(request),服务器给客户端返回的数据,称为"响应"(response);

客户端与服务器之间的交互有多种模式.

1.一问一答:一个请求对应一个响应.最常见,例如在"web开发"中.

2.一问多答:一个请求对应多个相应.这个场景最要涉及到"下载".

3.多问一答:多个请求对应一个响应.这个场景主要涉及到"上传".

4.多问多答:一个请求可能对应多个响应,一个响应也可能对应多个请求,主要涉及到"远程控制/远程桌面"

二.TCP / UDP 特点

TCP 的特点是:有连接 可靠传输 面向字节流 全双工

UDP 的特点是:无连接 不可靠传输 面向数据报 全双工

有连接 / 无连接: 此处的连接不是物理意义上的连接,而是抽象,虚拟的连接,举个简单的例子,当我们打电话时,一边拨号,一边接通,此时才能通话,如果一方不接通,就无法进行通话,这就叫做有连接,连接首先的特点是双方都能认同.无连接类似发短信,无论你是否同意,我都能给你将信息发过去.计算机中的"网络连接"即是通信双方,各自保存对方的信息,客户端中,有一些数据结构记录了谁是他的服务器,服务器中也有一些数据结构,记录了谁是他的客户端~~

可靠传输 / 不可靠传输: 网络上"异常情况"很多,无论使用什么样的软硬件的技术手段,都无法保证网络数据100%从A运送到B.此处我们的"可靠传输"指的是尽可能的完成数据传输,虽然无法保证数据到达对方,但至少可以知道这个数据对方是否收到了,此处的可靠传输,主要指的是发送的数据没收到,发送方能否清楚地感知到.

面向字节流 / 面向数据报: 此处的字节流和文件中的字节流完全一致,网络中传输的数据的基本单位是字节.面向数据报,每次传输的单位就是一个数据报(特定的结构,数据报由一系列的字节构成).

全双工 / 半双工: 一个信息渠道可以双向通信称为全双工,只能单向通信成为半双工.

三.UDP 回显服务器

核心的类有两个:

1.DatagramSocket: 负责对 socket 文件读写,也就是借助网卡发送数据

2.DatagramPacket: 面向数据报,每次发送接收数据的基本单位,就是一个UDP数据报

UDP 服务器

public class UdpEchoServer {DatagramSocket socket=null;// 第一步: 创建DatagramSocket对象,而后的操作针对socket对象完成public UdpEchoServer(int port) throws IOException {socket=new DatagramSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");while (true) {  // 对于服务器,需要不断接受请求,返回响应,于是需要用一个 while 循环// 1.接受请求并解析,byte可以保存收到的消息正文DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);String request=new String(requestPacket.getData(),0,requestPacket.getLength());// 2.根据请求响应计算String response=process(request);DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());// 3.返回响应socket.send(responsePacket);System.out.printf("[%s:%d] req:%s, resp:%s\n",responsePacket.getAddress(),responsePacket.getPort(),request,response);}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer udpEcohoServer=new UdpEchoServer(9090);udpEcohoServer.start();}}

UDP 客户端

public class UdpEchoClient {private  DatagramSocket socket=null;private String serverIp;private int serverPort;public UdpEchoClient(String serverIp, int serverPort) throws SocketException {this.serverIp=serverIp;this.serverPort=serverPort;socket=new DatagramSocket();}public void start() throws IOException {System.out.println("客户端启动!");Scanner scanner=new Scanner(System.in);while (true) {System.out.printf("-> ");// 1.从控制台读取流程if (!scanner.hasNext()) {break;}String request=scanner.next();// 2.构造请求并发送DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort);socket.send(requestPacket);// 3.读取服务器响应DatagramPacket responsePacker=new DatagramPacket(new byte[4096],4096);socket.receive(responsePacker);// 4.把响应显示在控制台上String response=new String(responsePacker.getData(),0,responsePacker.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client=new UdpEchoClient("127.0.0.1",9090);client.start();}}

UDP字典

public class UdpDictServer extends UdpEchoServer {private HashMap<String,String> hashMap=new HashMap<>();public UdpDictServer(int port) throws IOException {super(port);hashMap.put("小鸡","chicken");hashMap.put("小猫","cat");hashMap.put("小狗","dog");}@Overridepublic String process(String request) {return hashMap.getOrDefault(request,"该词典中没有这个单词");}public static void main(String[] args) throws IOException {UdpDictServer udpDictServer=new UdpDictServer(9090);udpDictServer.start();}
}

四.TCP 回显服务器

TCP 服务器

public class TcpEchoServer {private ServerSocket serverSocket=null;public TcpEchoServer(int port) throws IOException {serverSocket=new ServerSocket(port);}public void start() throws IOException {System.out.println("服务端启动!\n");while (true) {// 通过accept"接听电话"后才能进行通信Socket clientSocket=serverSocket.accept();Thread t=new Thread(()->{  // 引入多线程,可以同时服务多个服务器processConnection(clientSocket);});t.start();}}private void processConnection(Socket clientSocket) {System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());// 循环读取客户请求并反映try (InputStream inputStream= clientSocket.getInputStream();OutputStream outputStream=clientSocket.getOutputStream()){while (true) {// 通过inputStream读取数据Scanner scanner=new Scanner(inputStream);if (!scanner.hasNext()) {System.out.printf("[%s:%d] 客户端下线!\n",clientSocket.getInetAddress(),clientSocket.getPort());break;}// 1.读取请求并解析,这里有隐藏约定,next读的时候要以 空格 或 换行符 结束;String request=scanner.next();// 2.响应请求并计算String response=process(request);// 3.把响应返回给客户端//通过这种方式可以写回,但是这种方式不方便给返回的响应中添加\n// outputStream.write(response.getBytes(),0,response.getBytes().length);// 也可以给 outputstream 套上一层,完成更方便的写入。PrintWriter printWriter=new PrintWriter(outputStream);printWriter.println(response);printWriter.flush();System.out.printf("[%s:%d] req:%s, resp:%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);}} catch (IOException e) {throw new RuntimeException(e);}}private String process(String request) {return  request;}public static void main(String[] args) throws IOException {TcpEchoServer tcpEcohoServer=new TcpEchoServer(9090);tcpEcohoServer.start();}
}

TCP 客户端

public class TcpEchoClient {private Socket socket=null;public TcpEchoClient(String serverIP, int serverPort) throws IOException {socket=new Socket(serverIP,serverPort);}public void start() throws IOException {System.out.println("客户端上线!\n");// 1.从控制台读取输入的字符串try (InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()){Scanner scannerConsole=new Scanner(System.in);Scanner scannerNetwork=new Scanner(inputStream);PrintWriter writer=new PrintWriter(outputStream);while (true) {System.out.print("-> ");if (!scannerConsole.hasNext()) {break;}String request=scannerConsole.next();// 2.把请求发送给服务器,这里需要有 println 来发送,为了让发送结尾带 \n// 这里是和 scanner.next() 呼应writer.println(request);// 主动刷新缓冲器,确保数据发送writer.flush();// 3.从服务器读取响应String response=scannerNetwork.next();// 4.把响应显示出来System.out.println(response);}}finally {socket.close();}}public static void main(String[] args) throws IOException {TcpEchoClient client=new TcpEchoClient("127.0.0.1",9090);client.start();}}


相关文章:

  • neo4j:ubuntu环境下的安装与使用
  • Spring Boot 点餐系统:餐饮界的技术革新
  • 【mac开发入坑指南】能让你的终端好用一万倍的神仙组合iTerm2 + oh-my-zsh
  • 【Rust练习】16.方法和关联函数
  • 解决远程连接AlpineLinux Mysql/MariaDB 无法连接的问题
  • Nginx反向代理配置支持websocket
  • 第18周 第1章Ajax基础知识
  • Axure原型系统:药企内部管理平台原型设计
  • Html--笔记01:使用软件vscode,简介Html5--基础骨架以及标题、段落、图片标签的使用
  • TypeScript 设计模式之【单例模式】
  • 数据备份策略:保障数据安全的关键
  • 从预测性维护到智能物流:ARM边缘计算控制器的工业实践
  • C++——编写一个函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度。用指针方法处理。
  • 入门插件开发-列表插件开发-第三节:案例演示——setFilter事件讲解
  • LLMs之RAG:MemoRAG(利用其记忆模型来实现对整个数据库的全局理解)的简介、安装和使用方法、案例应用之详细攻略
  • [译]Python中的类属性与实例属性的区别
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 2017年终总结、随想
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • C# 免费离线人脸识别 2.0 Demo
  • ECMAScript6(0):ES6简明参考手册
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • IDEA常用插件整理
  • If…else
  • js正则,这点儿就够用了
  • MySQL数据库运维之数据恢复
  • PermissionScope Swift4 兼容问题
  • yii2权限控制rbac之rule详细讲解
  • 聊聊sentinel的DegradeSlot
  • 如何优雅地使用 Sublime Text
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 在electron中实现跨域请求,无需更改服务器端设置
  • nb
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • !$boo在php中什么意思,php前戏
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (1)svelte 教程:hello world
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (JS基础)String 类型
  • (十五)使用Nexus创建Maven私服
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .net 程序发生了一个不可捕获的异常
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • @cacheable 是否缓存成功_Spring Cache缓存注解
  • [ C++ ] STL_vector -- 迭代器失效问题
  • [ vulhub漏洞复现篇 ] AppWeb认证绕过漏洞(CVE-2018-8715)
  • [20180129]bash显示path环境变量.txt
  • [AIGC] 使用Curl进行网络请求的常见用法