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

实现回显服务器(基于UDP)

目录

一.回显服务器的基本概念

二.回显服务器的简单示意图

三.实现回显服务器(基于UDP)必须要知道的API 

1.DatagramSocket

2.DatagramPacket 

3.InetSocketAddress

4.二者区别 

1. 功能职责

2. 核心作用

3. 使用场景流程

四.实现服务器端的主要思路 

代码部分如下

实现服务器端的注意事项 

五.实现客户端的主要思路

实现客户端的注意事项 

六.完整代码 

运行测试结果 


一.回显服务器的基本概念

回显服务器(Echo)可以看成是网络编程中的"hello world",是学习网络编程的入门。简单介绍一下,回显服务器就是服务端收到什么,就给客户端发送什么。我会基于UDP来实现一个回显服务器。

二.回显服务器的简单示意图

三.实现回显服务器(基于UDP)必须要知道的API 

1.DatagramSocket

方法签名方法说明
DatagramSocket创建一个 UDP 数据报套接字的 Socket,绑定到本机指定的端口(一般用于服务端)
DatagramSocket(int port)创建一个 UDP 数据报套接字的 Socket,绑定到本机任意一个随机端口(一般用于客户端)

void receive(DatagramPacket p)

   

从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待
void send(DatagramPacket p)从此套接字发送数据报(不会阻塞等待,直接发送)
void close()关闭此数据报套接字

2.DatagramPacket 

方法签名方法说明
DatagramPacket(byte[] buf, int length)构造一个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length)。address指定目的主机的IP和端口号
InetAddress getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址
int getPort()从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号
byte[] getData()获取数据报中的数据

3.InetSocketAddress

方法签名方法说明
InetSocketAddress(InetAddress addr, int port)创建一个 Socket 地址,包含 IP 地址和端口号

4.二者区别 

1. 功能职责

  • DatagramSocket:是套接字类,相当于 “码头”,负责发送、接收DatagramPacket数据报,还能绑定端口、管理网络连接(虽 UDP 无连接,但它提供收发的基础通道 ),比如通过send发送数据报、receive接收数据报,close关闭套接字。
  • DatagramPacket:是数据报类,相当于 “集装箱”,负责封装 UDP 通信中要发送或接收的数据,包含数据内容、数据长度,以及发送 / 接收时的目标地址(IP + 端口 )或源地址信息。

2. 核心作用

  • DatagramSocket聚焦网络收发操作,决定 “怎么传”(用哪个端口、怎么建立收发通道 );
  • DatagramPacket聚焦数据封装,决定 “传什么”(数据内容 )和 “传给谁 / 从哪收”(地址信息 ) 。

3. 使用场景流程

UDP 通信时,先创建DatagramSocket作为收发的 “通道”,再创建DatagramPacket封装数据 / 地址,最后通过DatagramSocketsend/receive完成数据收发 。比如客户端用DatagramSocket发送封装了数据和目标地址的DatagramPacket;服务器端用DatagramSocket绑定端口,接收包含数据和源地址的DatagramPacket 。

四.实现服务器端的主要思路 

1.读取请求并解析

2.根据请求,计算响应

3.把响应返回给客户端

4.打印日志(方便观察)

代码部分如下

public void start() throws IOException {while(true){//1.读取请求并解析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);//3.把响应返回给客户端DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);//4.打印日志System.out.printf("[%s:%d,request:%s response:%s]\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}

实现服务器端的注意事项 

五.实现客户端的主要思路

1.在控制台读取用户要输入的内容

2.把请求发送给服务器

3.发送请求数据包给服务器端

4.接收服务器端的响应

5.把从服务器读取的数据进行解析,打印出来

  public void start() throws IOException {Scanner scanner=new Scanner(System.in);while(true){System.out.println("请输入内容");//按ctrl+d会breakif(!scanner.hasNext()){break;}//1。从控制台读取用户要输入的内容String resquest=scanner.next();//2.把请求发送给服务器DatagramPacket resquestPacket=new DatagramPacket(resquest.getBytes(),resquest.getBytes().length,InetAddress.getByName(ServerIp),ServerPort);
//            socket.receive(resquestPacket);//3.发送请求数据包给服务器端socket.send(resquestPacket);//4.接收服务器端的响应DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);//5.把从服务器读取的数据进行解析,打印出来String response=new String(responsePacket.getData(),0,responsePacket.getLength());System.out.println(response);}}

实现客户端的注意事项 

六.完整代码 

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket=null;//记录ip与端口号private String ServerIp;private int ServerPort;//服务器的ip与端口号public UdpEchoClient(String ServerIp,int ServerPort) throws SocketException {this.ServerIp=ServerIp;this.ServerPort=ServerPort;//客户端这里的端口号等到操作系统随机分配socket=new DatagramSocket();}public void start() throws IOException {Scanner scanner=new Scanner(System.in);while(true){System.out.println("请输入内容");//按ctrl+d会breakif(!scanner.hasNext()){break;}//1。从控制台读取用户要输入的内容String resquest=scanner.next();//2.把请求发送给服务器DatagramPacket resquestPacket=new DatagramPacket(resquest.getBytes(),resquest.getBytes().length,InetAddress.getByName(ServerIp),ServerPort);
//            socket.receive(resquestPacket);//3.发送请求数据包给服务器端socket.send(resquestPacket);//4.接收服务器端的响应DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);//5.把从服务器读取的数据进行解析,打印出来String response=new String(responsePacket.getData(),0,responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient udpEchoClient=new UdpEchoClient("127.0.0.1",1777);udpEchoClient.start();}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;public class UdpEchoServer {private DatagramSocket socket=null;public UdpEchoServer(int port) throws SocketException {socket=new DatagramSocket(port);}public void start() throws IOException {while(true){//1.读取请求并解析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);//3.把响应返回给客户端DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);//4.打印日志System.out.printf("[%s:%d,request:%s response:%s]\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}//将private改为public,方便方面有新功能,可以进行重写public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer udpEchoServer=new UdpEchoServer(1777);udpEchoServer.start();}
}

运行测试结果 

http://www.xdnf.cn/news/14312.html

相关文章:

  • 【Linux系列】HEIC文件类型
  • 使用 vscode 开发 uni-app 项目时如何解决 manifest.json 文件注释报错的问题
  • 学习设计模式《十三》——迭代器模式
  • uniapp打包安卓和ios
  • 前端资源帖
  • JUC核心解析系列(二)——显式锁深度解析
  • Flink 与 Hive 深度集成
  • Qt .pro配置gcc相关命令(三):-W1、-L、-rpath和-rpath-link
  • 删除链表的倒数第N个结点
  • 系统架构设计师 2
  • 音频水印——PerTh Watermarker
  • 《Attention Is All You Need》解读
  • 佛山SAP本地化代理商和实施公司推荐,哪家更专业?
  • Emacs定制:文件管理dired
  • 为应对激烈竞争环境,IBMS系统如何提升企业管理效率
  • [Java恶补day24] 整理模板·考点三【二分查找】
  • 2.1话题发布
  • 探索Agent的发展潜力:大模型与具身智能的融合
  • 浅谈拼写纠错
  • 调用AkShare获取A股股票基本信息
  • 布局和约束相关的生命周期(layoutIfNeeded,updateConstraintsIfNeeded)
  • iOS安全和逆向系列教程 第19篇:ARM64汇编语言基础与逆向分析
  • 使用清华大学的 Hugging Face 镜像
  • PTP时间同步实战测试clock master/slave 直连校时+PPS测试
  • 第8章——8天Python从入门到精通【itheima】-88~90-Python的文件操作(文件的写出+文件的追加+综合案例)
  • 强化学习 PPO
  • GRUB2 启动配置的工作原理与优先级规则详解
  • 软件测试银行项目之“信用卡测试流程”
  • LlamaIndex 工作流 并发执行
  • Day13_C语言基础项目实战