【网络编程】UDP实现回显服务器

avatar
作者
猴君
阅读量:1

一.网络编程的基本术语.

  • 客户端

客户端是为用户提供本地服务的程序,通常位于用户设备上。也称为用户端,是相对于服务器而言的。它主要指安装在用户设备上的程序,这些程序能够与服务器进行通信,从而获取服务或者执行特定功能。在互联网应用中,常见的客户端包括网页浏览器、电子邮件客户端和即时通讯软件等。它们需要与远端的服务器建立连接,以便接收如数据库服务、邮件服务等网络服务。

  • 服务器

服务器则是为其他程序或设备提供功能的计算机或软件。一种专门设计用来处理数据请求并提供服务的计算设备。它具备高速的CPU、大容量的存储空间以及强大的I/O吞吐能力,能够长时间稳定运行。服务器的主要作用是在网络中为客户机(如个人电脑、智能手机等)提供诸如网站访问、文件存储、数据处理等各种计算和应用服务。

  • 网络编程

网络编程 : 指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。

  • 套接字(Socket)

套接字,常称为socket,是计算机网络中用于实现不同主机之间的进程双向通信的端点。在网络编程中,套接字充当了非常重要的角色,它定义了一套标准的API,允许程序员在不同的计算机之间发送和接收数据.是网络编程中实现不同主机间进程通信的一种技术规范和编程接口。

  • 流套字节

使用传输层TCP协议 , 对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。

  • 数据报套接字

使用传输层UDP协议 , 对于数据报来说,可以简单的理解为,传输数据是⼀块⼀块的,发送⼀块数据假如100个字节,必须⼀次发送,接收也必须⼀次接收100个字节,而不能分100次,每次接收1个字节。

  • 原始套字节

原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。

  • TCP和UDP的特点

TCP特点:

  1. 有连接 : 连接的双方都需要认同(本质上就是通信双方都保存有通信双方各自的信息)
  2. 可靠传输 : 主要是指发送方放的信息是否被收到 , 发送方能够清楚的感知到.
  3. 面向字节流 : 传输的基本单位是以字节为基本单位
  4. 全双工 : 一个信道,可以双向通信. 只能单向通信就称为’‘半双工’’

UDP的特点:
1.无连接. 2. 不可靠传输. 3.面向字节报 4.全双工.

二.常用API

DatagramSocket
构造方法:
在这里插入图片描述
常用方法:
在这里插入图片描述
DatagramPacket
构造方法:
在这里插入图片描述
基本方法:
在这里插入图片描述

三.基于UDP回显服务器.

客户端代码

package Demo1;  import java.io.IOException; import java.net.*; import java.nio.charset.StandardCharsets; import java.util.Scanner;  public class udpEchoClint {     private DatagramSocket datagramSocket = null;     private String  serverIP;     private int serverPort;     //客户端要给服务器发送请求的前提就是知道服务器的地址     public udpEchoClint(String serverIP,int serverPort) throws SocketException {         datagramSocket = new DatagramSocket();         this.serverIP= serverIP;         this.serverPort = serverPort;     }     public void start() throws IOException {         System.out.println("客户端启动~~");         Scanner scanner = new Scanner(System.in);         while(true){             System.out.print("->");             if(!scanner.hasNext()){                 break;             }             //1.从控制台读取要发送的请求数据.             String request = scanner.next();             //2.构造一个请求并发送.             DatagramPacket requestPacket = new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),                     request.getBytes().length,                     InetAddress.getByName(serverIP),                     serverPort                     );             datagramSocket.send(requestPacket);             //3.读取服务器的响应.             DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);             datagramSocket.receive(responsePacket);             //4.把响应显示到控制台上             String response = new String(responsePacket.getData(),0,responsePacket.getLength());             System.out.println(response);         }     }     public static void main(String[] args) throws IOException {         udpEchoClint clint = new udpEchoClint("127.0.0.1",9090);         clint.start();     } }  

服务器代码

package Demo1;  import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; import java.nio.charset.StandardCharsets;  public class udpEchoServer {     private DatagramSocket datagramSocket = null;     public udpEchoServer(int port) throws SocketException {         datagramSocket = new DatagramSocket(port);     }     //服务器的启动逻辑.     public void start() throws IOException {         System.out.println("服务器启动!!");         //对于服务器来说,需要不停的收到请求,返回响应          while(true){             //每次循环就是处理一个请求返回响应的过程             //1.读取请求并解析             DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);                 //这个字节数组,保存收到的消息正文(应用层数据包),也就是应用层数据报的载荷部分             datagramSocket.receive(requestPacket);                 //将消息正文转化为字符串.             String request = new String(requestPacket.getData(),0,requestPacket.getLength());             //2.根据请求计算响应(对于回显服务器来说,这一步啥也不用干)             String response = process(request);             //3.把响应返回给客户端             //构造一个响应对象.             DatagramPacket responsePacket = new DatagramPacket(response.getBytes(StandardCharsets.UTF_8),                     response.getBytes().length,                     requestPacket.getSocketAddress() //得到一个INetAddress对象吗,里面存储了客户端的IP和端口号.                     // 会把客户端的源IP和端口号,作为目的IP和目的端口号.              );             datagramSocket.send(responsePacket);              //打印日志:             System.out.printf("[%s,%d],request: %s, response: %s",                     responsePacket.getAddress().toString(),                     responsePacket.getPort(),                     request,                     response             );         }     }     public String process(String request){         //回显服务器,返回要求.         return request;     }     public static void main(String[] args) throws IOException {         udpEchoServer server = new udpEchoServer(9090);         //1024<端口号范围<65535         server.start();     } }  

运行结果:
在这里插入图片描述
在这里插入图片描述
具体的执行流程:

  1. 服务器启动===>启动之后,立即进入while循环,执行到receive,进入阻塞,此时客户端还没有发来请求~~
  2. 客户端启动===>启动之后,立即进入while虚幻,执行到hasNext这里~~进入阻塞,此时用户没有在控制台输入任何内容.
  3. 用户在客户端的控制台中输入字符串,按下回车.此时hasNext阻塞解除,next会返回刚才输入的内容.
    基于用户输入的内容,构造出一个DatagramPacket对象,并进行send~~
    send执行完毕之后,继续执行到receive操作,等待服务器返回的响应数据(此时服务器还没有返回响应,这里也会阻塞).
  4. 服务器收到请求之后,就会从receive的阻塞中返回.
    返回之后,就会根据读到的DatagramPacket对象,构造String request,通过process方法构造一个String response
    再根据response构造一个DatagramPacket表示响应对象,再通过send来进行发送给客户端
    执行这个过程中,客户端也始终在阻塞等待!!
  5. 客户端从receive中返回执行,就能够得到服务器返回的相应.并且打印在控制台上.
    于此同时,服务器进入下一次循环,也要进入到第二次的receive阻塞,等待下个请求~~

四.编写一个英译汉的服务器

利用上述写的回显服务器.只需要重写process
代码示例:

package Demo1;  import java.io.IOException; import java.net.SocketException; import java.util.HashMap;  public class UdpDictServer extends udpEchoServer{     HashMap<String,String> hashMap = new HashMap<>();     public UdpDictServer(int port) throws SocketException {         super(port);         hashMap.put("cat","小猫");         hashMap.put("dog","小狗");         hashMap.put("pig","小猪");     }     @Override     public String process(String request) {         return hashMap.getOrDefault(request,"您输入的单词不存在");     }      public static void main(String[] args) throws IOException {         UdpDictServer server = new UdpDictServer(9090);         server.start();     } }  

运行结果:
在这里插入图片描述
在这里插入图片描述

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!