前言:
回显服务器是返回与客户端相同请求数据的一种服务器实现模式,服务器通过解析客户端发送的数据包,构造和返回与请求数据包内容一致的数据包。在使用代码实现之前,首先介绍一下此次会使用到的相关类:
DatagramSocket:
简介:DatagramSocket这个类是Java使用来实现UDP的socket的一个类,其主要作用是实现数据报的发送和接收。
构造方法:
1,DatagramSocket():不带参数的构造方法,会生成一个由系统随机分配端口号的对象。
2,DatagramSocket(int prot):可以指定任意端口号,但通常端口号需要指定在大于1024,小于65535。
DatagramPacket:
简介:
DatagramPacket这个类在Java中代表数据报,是DatagramSocket实现发送和接收方法需要使用到的对象。
构造方法:
1,DatagramPacket(byte[] buf,int length):通过一个字符数组来读取DatagramSocket接收到的数据报,读取长度为length。
2,DatagramPacket(byte[] buf, int offset, int length):通过一个字符数组来读取DatagramSocket接收到的数据报,读取起点为下标offset,读取长度为length。
3,DatagramPacket(byte[] buf, int length, InetAddress addr, int port):发送一个字节数组长度为length的内容,需要指定IP地址和端口号。
4,DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):发送一个字节数组中起点为offset,长度为length的内容,需要指定IP地址和端口号。
以下是使用idea的代码实现:
服务器实现:
简介:回显服务器主要实现以下几个功能:1,接收客户端信息;2,解析并构造返回的数据;3,发送数据;4,记录服务器工作日志。通过对以上两个类的了解,想要通过UPD实现服务器与客户端,在接收发送数据的功能实现中需要构建 DatagramSocket 对象来实现发送与接收方法调用,通过 DatagramPacket 对象来实现数据包的构建,这里两个类的关系相当于码头与货物的关系, DatagramSocket 对象对应码头,DatagramPacket 对象对应货物。值得注意的是 DatagramPacket 对象所指代的数据包其实是数据报,在考虑使用其作为发送数据的数据报需要注意为其提供相关的IP地址和端口号
public class UdpEchoServer {
private DatagramSocket socket = null;
public UdpEchoserver(int port) throws SocketException {
socket = new DatagramSocket(port);
}
public void start() throws IOException {
System.out.println("服务器启动");
//服务器功能:接收数据,解析数据包,构造响应数据包,返回响应
while(true) {
//此处使用死循环来使服务器一直处于工作状态
DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
//此处构建字节数组的作用是通过其来接收客户端的请求,后面的整形指该字节数组的读取长度
socket.receive(requestPacket);
String request = new String(requestPacket.getData(),0,requestPacket.getLength());
//此处需要注意构建字符串对象所申请的长度区间,是从0到requestPacket所接收的有效范围
String response = process(request);
//由于是实现回显服务器,因此直接返回接收到的文本内容
DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getAddress(),requestPacket.getPort());
//此次构建该对象的目的是为socket的send()方法构造返回参数,需要使用到客户端的IP地址和端口号作为构造参数
socket.send(responsePacket);
System.out.printf("[%s,%d] res: %s,req: %s",requestPacket.getAddress().toString(),requestPacket.getPort(),
request,response);
//此处为日志打印,显示客户端IP地址和端口号及请求与响应
}
}
private String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
UdpEchoserver udpEchoserver = new UdpEchoserver(9090);
udpEchoserver.start();
}
}
客户端实现:
public class UdpEchoClient {
//客户端功能:1,通过控制台输入,发送信息 2,接收服务器响应并将其打印到控制台上
private DatagramSocket socket = null;
private int severPort;
private String severIp;
private UdpEchoClient(int severPort,String severIp) throws SocketException {
socket = new DatagramSocket();
this.severIp = severIp;
this.severPort = severPort;
}
public void start() throws IOException {
System.out.println("客户端启动");
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.print("请输入请求:");
if(!scanner.hasNext()) {
break;
}
String request = scanner.next();
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(this.severIp),this.severPort);
socket.send(requestPacket);
DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
socket.receive(responsePacket);
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(9090,"127.0.0.1");
udpEchoClient.start();
}
}