1.了解什么是回显
回显指当本地终端向远端设备发送数据时,远端设备将接收到的数据再发送回本地终端显示出来的过程。比如我们在命令行中输入一些指令后,服务器返回的相关信息显示在命令行界面上,这就是一种回显情况,像用"ping"命令去测试网络连通性时,返回的如IP地址、响应时间等信息的显示就是回显的体现。
2.基于UDP实现回显服务器需要使用的方法
1.DatagramSocket,可以这么理解,这就是一个电话,用来接收和发送信息的
receive方法用来接收信息
send方法用来发送信息的
close方法,你信息发完了,不使用就需要进行关机
2.DatagramPacket,就是你的电话发送的信息,这个信息就像快递一样,打包一起发过去,他也有一个名字叫做数据报,对于客户端来说,我们在将这个快递"寄"出去时,需要填写对方的IP地址和端口号,来指定寄给谁,然而对方(也就是服务器)不需要知道我们的地址,因为,我们将这个快递寄出去时,快递上就写了我们(客服端)的地址和端口号服务器获取数据报的地址和端口号:数据报名.getSocketAddress()
3.代码解析与实现
服务端代码:
package notwork;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UdpEchoSever_3 {
DatagramSocket socket=null;
//给服务器搞一个"电话",让他可以使用这个电话来接收和发送信息
public UdpEchoSever_3(int port) throws SocketException {
socket=new DatagramSocket(port);
//指定一个端口让服务器来使用
}
public void start() throws IOException {
//打印个信息,表示服务器启动
System.out.println("服务器启动");
/**
* 循环一次代表处理一次请求,也就是对方发个问题过来,你给他解决,
*
* 然而处理请求的过程一般分为三步
* 1.读取请求并解析
* 2.根据请求,计算响应(服务器最为关键的一步)
* 3.把响应返回给客户端
**/
while(true){
//1.读取请求并解析
// DatagramPacket 表示一个数据报,此处传入的字节数组,就保存UDP的载荷部分。
DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);
//接收客户端发来的数据报
socket.receive(requestPacket);
//把读取到的二进制数据,转换成字符串,只是构造有效的部分
String request=new String(requestPacket.getData(),0, requestPacket.getLength());
//2.根据请求,计算响应
//我们此处写的是回显服务器
//所以意思意思,写个计算响应的方法,将请求原封不动的返回一下
String reponse=process(request);
//3.把响应返回给客户端
//将字符串转化为字节数组,然后获取字节数组的长度,并使用接收的数据报获取客户端的IP地址和端口号
DatagramPacket reponsePacket=new DatagramPacket(reponse.getBytes(),reponse.getBytes().length, requestPacket.getSocketAddress());
//将响应的数据报发送给客户端
socket.send(reponsePacket);
//打印一下日志
System.out.printf("[%s:%d] rqs:%s rep:%s",requestPacket.getAddress(),requestPacket.getPort(),request,reponse);
}
}
//后续写其他服务器时,只需要修改一下计算响应的这个方法就行了
//可以继承这个类,然后重写process方法,将private修改为public就行
private String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
UdpEchoSever_3 sever_3=new UdpEchoSever_3(4565);
sever_3.start();
}
}
客户端代码:
package notwork;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class UdpEchoClient_3 {
private String IpSever;
private int portSever;
private DatagramSocket socket=null;
//和服务器不同,客户端是要先发出请求,所以第一个数据报是从客户端发出,需要知道服务器的IP地址和端口号
public UdpEchoClient_3(String ipSever, int portSever) throws SocketException {
this.IpSever = ipSever;
this.portSever = portSever;
socket=new DatagramSocket();
}
public void start() throws IOException {
Scanner scanner=new Scanner(System.in);
while(true){
//1.从控制台读取用户输入的信息
System.out.printf("请输入请求:");
if(!scanner.hasNext()){
break;
}
String request= scanner.next();
//2.把请求发送给服务器,构造一个数据报,将字符串转化为字节数组,加上字节数组的长度,以及将IP地址从字符串转化为指定的类型,加上端口号
DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,
InetAddress.getByName(IpSever),portSever);
//将数据报发送给服务器
socket.send(requestPacket);
//创建一个数据报对象用来接收服务器返回的数据报
DatagramPacket reponsePacket=new DatagramPacket(new byte[4096],4096);
//接收数据报
socket.receive(reponsePacket);
//将数据报的信息转化为字符串
String reponse=new String(reponsePacket.getData(),0,requestPacket.getLength());
//将响应的信息打印
System.out.println(reponse);
}
}
public static void main(String[] args) throws IOException {
//127.0.0.1通常被称为回环IP,可以将服务器和客户端在一台电脑上运行
UdpEchoClient_3 client_3=new UdpEchoClient_3("127.0.0.1",4565);
client_3.start();
}
}