实现回显服务器(基于UDP)_系统的回显服务
目录
一.回显服务器的基本概念
二.回显服务器的简单示意图
三.实现回显服务器(基于UDP)必须要知道的API
1.DatagramSocket
2.DatagramPacket
3.InetSocketAddress
4.二者区别
1. 功能职责
2. 核心作用
3. 使用场景流程
四.实现服务器端的主要思路
代码部分如下
实现服务器端的注意事项
五.实现客户端的主要思路
实现客户端的注意事项
六.完整代码
运行测试结果
一.回显服务器的基本概念
回显服务器(Echo)可以看成是网络编程中的\"hello world\",是学习网络编程的入门。简单介绍一下,回显服务器就是服务端收到什么,就给客户端发送什么。我会基于UDP来实现一个回显服务器。
二.回显服务器的简单示意图
三.实现回显服务器(基于UDP)必须要知道的API
1.DatagramSocket
void receive(DatagramPacket p)
2.DatagramPacket
DatagramPacket
以用来接收数据报,接收的数据保存在字节数组(第一个参数buf
)中,接收指定长度(第二个参数length
)DatagramPacket
以用来发送数据报,发送的数据为字节数组(第一个参数buf
)中,从0
到指定长度(第二个参数length
)。address
指定目的主机的IP
和端口号IP
地址;或从发送的数据报中,获取接收端主机IP
地址3.InetSocketAddress
4.二者区别
1. 功能职责
DatagramSocket
:是套接字类,相当于 “码头”,负责发送、接收DatagramPacket
数据报,还能绑定端口、管理网络连接(虽 UDP 无连接,但它提供收发的基础通道 ),比如通过send
发送数据报、receive
接收数据报,close
关闭套接字。DatagramPacket
:是数据报类,相当于 “集装箱”,负责封装 UDP 通信中要发送或接收的数据,包含数据内容、数据长度,以及发送 / 接收时的目标地址(IP + 端口 )或源地址信息。
2. 核心作用
DatagramSocket
聚焦网络收发操作,决定 “怎么传”(用哪个端口、怎么建立收发通道 );DatagramPacket
聚焦数据封装,决定 “传什么”(数据内容 )和 “传给谁 / 从哪收”(地址信息 ) 。
3. 使用场景流程
UDP 通信时,先创建DatagramSocket
作为收发的 “通道”,再创建DatagramPacket
封装数据 / 地址,最后通过DatagramSocket
的send
/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会break if(!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会break if(!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(); }}