基于UDP协议实现回显服务器和客户端

由于我也是入门啦,实现的这个服务器目前仅支持本机访问~

一、回显服务器是什么?

回显服务器是指客户端发送给服务器什么样的请求,服务器就原封不动的将请求返回给客户端进而展示给用户

二、如何实现回显服务器

1.实例化socket对象

代码如下:

import java.net.DatagramSocket;
import java.net.SocketException;
/**
 * 天气:晴天
 * 目标:Good Offer
 * Date    2021-01-04 10:53
 */
public class UDPEchoServer {
    //(1)初始化socket对象
    //在初始化的过程中要绑定端口号,使得主机可以找到对应的应用程序
    private DatagramSocket socket = null;
    public UDPEchoServer(int port) throws SocketException {
       socket = new DatagramSocket(port);
    }
}

2.进入主循环

进入主循环完成步骤有3个:
(1)读取并解析请求
(2)根据请求计算响应
(3)将响应写回客户端
代码如下:

public void start() throws IOException {
        System.out.println("服务器开始启动");
        //(2)进入主循环
        //主循环是一个死循环,因为服务器端也不知道客户端会什么时候发送请求,所以要随时准备
        while(true){
           // a)解析请求数据
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);
            //由于得到的请求是一个字节数组,处理不方便,此处就把它转换为String类型
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());
            // b)根据请求计算响应
            String response = process(request);
            //注意:将response包装诶Packet的时候要指定它将数据包发给谁
            // requestPacket.getSocketAddress()就指定了数据包将要发送的目的IP和端口号
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());
            //c)将响应写回客户端
            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;
    }

服务器端完整的代码如下:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * 天气:晴天
 * 目标:Good Offer
 * Date    2021-01-04 10:53
 */
public class UDPEchoServer {
    //(1)初始化socket对象
    //在初始化的过程中要绑定端口号,使得主机可以找到对应的应用程序
    private DatagramSocket socket = null;
    public UDPEchoServer(int port) throws SocketException {
       socket = new DatagramSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器开始启动");
        //(2)进入主循环
        //主循环是一个死循环,因为服务器端也不知道客户端会什么时候发送请求,所以要随时准备
        while(true){
           // a)解析请求数据
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);
            //由于得到的请求是一个字节数组,处理不方便,此处就把它转换为String类型
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());
            // b)根据请求计算响应
            String response = process(request);
            //注意:将response包装诶Packet的时候要指定它将数据包发给谁
            // requestPacket.getSocketAddress()就指定了数据包将要发送的目的IP和端口号
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());
            //c)将响应写回客户端
            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(9094);
        server.start();
    }
}

三、如何实现回显服务器的客户端

1.实例化socket对象

代码如下:

import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * 天气:晴天
 * 目标:Good Offer
 * Date    2021-01-04 11:10
 */
public class UDPEchoClientServer {
    //(1)初始化socket对象
    private DatagramSocket socket = null;
    private String serverIp;
    private int port;

    public UDPEchoClientServer(String serverIp, int port) throws SocketException {
        this.serverIp = serverIp;
        this.port = port;
        //注意:客户端初始化的时候不需要指定端口号(IP地址定位主机,端口号定位了应用程序)
        //指定了可能会催用户使用主机应用程序的时候出现一些不必要的麻烦
        socket = new DatagramSocket();
    }
}

2.进入主循环

进入主循环完成步骤有4个:
(1)读取用户数据
(2)构造请求发送给服务器
(3)从服务器读取响应
(4)将响应写回客户端
代码如下:

  public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        //(2)进入主循环
        while(true){
            //a)读取用户数据
            System.out.println("输入请求:->");
            String request = scanner.nextLine();
            if (request.equals("exit")){
                System.out.println("退出");
                break;
            }
            //b)构造请求发给服务器
            //此处将request包装为packet的时候需要指定端口号和主机号
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(serverIp),serverPort);
            socket.send(requestPacket);
            //c)从服务器端读取响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            String response = new String(responsePacket.getData(),0,requestPacket.getLength()).trim();
            //d)将响应写回客户端
            System.out.println(response);
        }
    }

客户端完整代码如下:

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

/**
 * 天气:晴天
 * 目标:Good Offer
 * Date    2021-01-04 11:10
 */
public class UDPEchoClientServer {
    //(1)初始化socket对象
    private DatagramSocket socket = null;
    private String serverIp;
    private int serverPort;

    public UDPEchoClientServer(String serverIp, int port) throws SocketException {
        this.serverIp = serverIp;
        this.serverPort = port;
        //注意:客户端初始化的时候不需要指定端口号(IP地址定位主机,端口号定位了应用程序)
        //指定了可能会催用户使用主机应用程序的时候出现一些不必要的麻烦
        socket = new DatagramSocket();
    }
    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        //(2)进入主循环
        while(true){
            //a)读取用户数据
            System.out.println("输入请求:->");
            String request = scanner.nextLine();
            if (request.equals("exit")){
                System.out.println("退出");
                break;
            }
            //b)构造请求发给服务器
            //此处将request包装为packet的时候需要指定端口号和主机号
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(serverIp),serverPort);
            socket.send(requestPacket);
            //c)从服务器端读取响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);
            String response = new String(responsePacket.getData(),0,responsePacket.getLength()).trim();
            //d)将响应写回客户端
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
    //这里的127.0.0.1是一个环回地址自己访问自己
        UDPEchoClientServer client = new UDPEchoClientServer("127.0.0.1",9094);
        client.start();
    }
}

运行结果截图:
基于UDP协议实现回显服务器和客户端_第1张图片基于UDP协议实现回显服务器和客户端_第2张图片
接下来,我试着写了个简单的英译汉服务器,客户端不变,只需要新建一个类继承服务器端即可!

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;

/**
 * 天气:晴天
 * 目标:Good Offer
 * Date    2021-01-04 11:40
 */
public class TranslateServer  extends UDPEchoServer{
    Map<String,String > dictionary = new HashMap<>();
    public TranslateServer(int port) throws SocketException {
        super(port);
        dictionary.put("happy","开心");
        dictionary.put("lucky","幸运");
        dictionary.put("nice","美好");
    }

    @Override
    public String process(String request) {
        return dictionary.getOrDefault(request,"超出我的词库啦,我会继续努力学习的~");
    }

    public static void main(String[] args) throws IOException {
        TranslateServer translate = new TranslateServer(9094);
        translate.start();
    }
}

运行截图:
基于UDP协议实现回显服务器和客户端_第3张图片基于UDP协议实现回显服务器和客户端_第4张图片

总结

最后我梳理一下服务器端和客户端的执行流程
基于UDP协议实现回显服务器和客户端_第5张图片终于入门服务器啦。继续努力搬砖,加油~

你可能感兴趣的:(小项目,socket)