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

目录

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

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

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

1.DatagramSocket

2.DatagramPacket

3.InetSocketAddress

4.二者区别

[1. 功能职责](#1. 功能职责)

[2. 核心作用](#2. 核心作用)

[3. 使用场景流程](#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.打印日志(方便观察)

代码部分如下

java 复制代码
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.把从服务器读取的数据进行解析,打印出来

java 复制代码
  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);

        }
    }

实现客户端的注意事项

六.完整代码

java 复制代码
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();


    }
}
java 复制代码
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();

    }
}

运行测试结果

相关推荐
敏叔V5873 分钟前
SpringBoot实现MCP
java·spring boot·后端
小袁拒绝摆烂4 分钟前
SpringCache整合SpringBoot使用
java·spring boot·后端
水果里面有苹果12 分钟前
19-C#静态方法与静态类
java·开发语言·c#
BUG批量生产者43 分钟前
[746] 使用最小花费爬楼梯
java·开发语言
慕y2741 小时前
Java学习第二十四部分——JavaServer Faces (JSF)
java·开发语言·学习
JosieBook1 小时前
【Java编程动手学】深入剖析Java网络编程:原理、协议与应用
java·udp·tcp
black_blank1 小时前
st表 && csp37 第四题 集体锻炼
java·数据结构·算法
我爱Jack1 小时前
Java List 使用详解:从入门到精通
java·开发语言·数据结构
手握风云-1 小时前
JavaEE初阶第八期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(六)
java·开发语言
天南星1 小时前
java-WebSocket在Java生态中的发展历程
java·后端·websocket