网站开发雷小天,制作个人主页,网站建设要架服务器,做网站需要懂哪些语言使用 JAVA 自带的api
目录 一、回显服务器 UdpEchoServer
服务器代码
客户端代码
二、翻译功能 UdpDictServer
在UdpDictServer里重写process方法 一、回显服务器 UdpEchoServer
/*** 回显服务器* 写一个简单的UDP的客户端/服务器 通信的程序* 这个程序没有啥业务逻辑只是单纯的调用socket api* 让客户端给服务器发送一个请求从控制台输入的字符串* 服务器收到字符串后会把这个字符串原封不动的返回给客户端客户端再显示出来运行过程* 1.先启动服务器 程序会进入while循环执行到receive()阻塞等待客户端的请求* 2.再启动客户端程序也会进入while循环执行到scanner 等待用户输入* 当用户输入字符串之后next就会返回构造请求数据并发送给服务器* 3.客户端发送数据之后* 服务器就会从receive中返回,进一步执行解析请求UDP报执行process计算响应操作最后执行send操作发送响应结果* 客户端接着执行到receive等待服务器的响应* 4.客户端接收到服务器响应的数据之后从receive中返回执行打印操作把响应的内容显示出来了* 5. 服务器执行完后重新进入while循环又执行到receive这里阻塞* 客户端执行完后也重新进入while循环执行到scanner这里阻塞**/
服务器代码
package network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {//创建一个DatagramSocket对象后续操作网卡的基础//socket 就是把网卡抽象成了文件//往socket文件中 写数据 就相当于通过网卡 发送数据//从socket文件中 读数据 就相当于通过网卡 接收数据//把网络通信和文件操作给统一了//在Java中就使用这个类来表示系统内部的 socket 文件了//常用的socket的方法receive(DatagramPacket P) ,send(DatagramPacket P), close//DatagramPacket 这个类用来表示一个UDP数据报//UDP是面向数据报的//每次进行传输都要以UDP数据包为基本单位private DatagramSocket socket null;//构造方法//服务器需要手动 显示指定端口号可以避免端口号冲突//客户端的socket 一般不能显示指定系统会随机分配一个端口//传入参数为 int portpublic UdpEchoServer(int port) throws SocketException {//手动指定端口号socket new DatagramSocket(port);//不带参数就是系统自动分配端口号
// socket new DatagramSocket();}//服务器启动方法//通过这个方法来启动服务器public void start() throws IOException {//服务器启动提示System.out.println(服务器启动);//服务器一般开了就不关了7*24小时不停歇运转所以是while(true)形式while(true){//1.读取请求并解析//创建UDP数据报 DatagramPacket对象 接收 客户端的数据//收到的数据需要用内存空间保存而DatagramPacket 内部不能自行分配内存空间//于是需要程序员手动把空间创建好交给DatagramPacket 进行处理,使用字节数组创建DatagramPacket requestPacket new DatagramPacket(new byte[4096],4096);//保存请求信息socket.receive(requestPacket);//接收请求信息。数据没来的时候会先阻塞直到客户端把请求发来为止//接收到的数据是以二进制的形式存储到DatagramPacket中了//要想显示出来需要将这个二进制数据转换成字符串String request new String(requestPacket.getData(),0,requestPacket.getLength());//参数为 二进制数据偏移量从0开始到requestPacket.getLength()这个数据结尾//2.根据请求计算响应//实际开发项目中服务器中最核心的步骤绝大数程序都是在完成这一部分String response process(request);//3.把响应写回到客户端// 创建响应对象DatagramPacket// 往这个对象里构造刚才的数据再通过send返回DatagramPacket responsePacket new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());//传入的参数 获取 数据的起始地址response.getBytes()数据的字节长度response.getBytes().length响应给 客户端的ip地址requestPacket.getSocketAddress()//指定字节数组缓冲区同时指定 客户端UDP请求报中的网卡信息requestPacket.getSocketAddress()其中包含了ip和端口号//网络传输使用字节以字节为单位socket.send(responsePacket);//4.打印一个日志把这次数据交互的详情打印出来System.out.printf([%s:%d] request%s response%s\n,requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);//打印的内容客户端的ip客户端的端口号 请求内容 响应内容}}//响应程序//这里只是简单回显
//这里写public才能被重写public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server new UdpEchoServer(9090);server.start();}
}客户端代码
package network;import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket null;//对网卡进行操作接收或发送数据报或者关闭//因为UDP报不会建立链接也不会存储对端的信息//所以在应用程序里把它存储起来private String serverIp ;private int serverPort 0;public UdpEchoClient(String ip , int port) throws SocketException {//客户端不能指定端口号码会端口冲突socket new DatagramSocket();//客户端 系统随机分配端口,不写参数就是系统随机分配//因为UDP报不会建立链接也不会存储对端的信息//所以在应用程序里把它存储起来//这里主要记录对端的 ip 和 端口serverIp ip;serverPort port;}//启动客户端程序public void start() throws IOException {//启动客户端提示System.out.println(客户端启动);//用户输入字符串Scanner scanner new Scanner(System.in);while(true){//1.从控制台读取数据作为请求System.out.print(-);//输入提示符String request scanner.next();//请求信息的内容//2.把请求内容构造成一个DatagramPacket对象发送给服务器DatagramPacket requestPacket new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort);//request.getBytes(),request.getBytes().length指定字节数组缓冲区同时指定 ip 和 端口号 InetAddress.getByName(serverIp),serverPortsocket.send(requestPacket);//发送UDP数据报//3.尝试读取客户端的响应DatagramPacket responsePacket new DatagramPacket(new byte[4096],4096);//创建一个空的UDP数据报来接收服务器的响应数据socket.receive(responsePacket);//4.把接收的响应数据 由二进制 转换成 字符串 显示出来String response new String(responsePacket.getData(),0,responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client new UdpEchoClient(127.0.0.1,9090);//该参数为对端服务器的ip和端口client.start();}
}运行结果
* 1.先启动服务器 程序会进入while循环执行到receive()阻塞等待客户端的请求 * 2.再启动客户端程序也会进入while循环执行到scanner 等待用户输入 * 当用户输入字符串之后next就会返回构造请求数据并发送给服务器
* 3.客户端发送数据之后
* 服务器就会从receive中返回,进一步执行解析请求UDP报执行process计算响应操作最后执行send操作发送响应结果
* 客户端接着执行到receive等待服务器的响应
* 4.客户端接收到服务器响应的数据之后从receive中返回执行打印操作把响应的内容显示出来了 * 5. 服务器执行完后重新进入while循环又执行到receive这里阻塞 * 客户端执行完后也重新进入while循环执行到scanner这里阻塞 * */
二、翻译功能 UdpDictServer
在回显服务器的基础上创建一个新的类继承回显服务器
在UdpDictServer里重写process方法
package network;import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;public class UdpDictServer extends UdpEchoServer{private MapString,String dict new HashMap();
//重写构造方法public UdpDictServer(int port) throws SocketException {super(port);dict.put(猫,cat);dict.put(狗,dog);dict.put(今天,today);dict.put(cat,猫);dict.put(dog,狗);dict.put(today,今天);}//重写父类 UdpEchoServer 的process方法//完成翻译逻辑翻译本质上是“查表”//刚才再dict哈希表里添加了一些键值对元素//刚才在重写的地方报错//原因是 父类的process方法之前用的是private//而private封装特性不能被重写//改成public之后就可以了Overridepublic String process(String request) {
// return dict.get(request);return dict.getOrDefault(request,该单词目前不在表中无法查看);//差不到表中信息可以给默认值}public static void main(String[] args) throws IOException {//如果端口号也是9090就与父类的端口号冲突了UdpDictServer dictServer new UdpDictServer(6666);//指定这个翻译功能 的端口是6666dictServer.start();//此时这里调用start的是子类UdpDictServer所以后面调用的process也是子类重写的方法//这里就是之前学到的多态}
}注意 翻译服务器里main方法里的端口要与父类不一样避免端口号冲突 同时客户端开启的时候要把端口号修改过来6060不然服务器就连错了 运行结果