【JavaEE】——回显服务器的实现

打印 上一主题 下一主题

主题 787|帖子 787|积分 2361

 

  
阿华代码,不是逆风,就是我疯

  
你们的点赞收藏是我进步最大的动力!!

  
盼望本文内容能够帮助到你!!

  目录
一:引入
1:根本概念
二:UDP socket API使用
1:socket文件
2:DatagramSocket类
(1)构造方法
(2)方法
3:DatagramPacket类
三:回显服务器——服务器
1:引入(必看)
2:服务器相应代码
(1)注释版本
(2)无注释版本
3:细节增补
4:特点
四:回显服务器——客户端
1:代码
(1)注释版本
(2)无注释版本
2:留意点
五:回显服务器过程笔墨梳理
六:知识增补

前引:本文代码发起反复敲打至少3遍!!!!

一:引入

1:网络编程的根本概念

网络编程就是通过写代码来完成基于网络的跨主机通信
本质上是学习传输层给应用层提供的一系列的API,通过API把数据交给传输层,在颠末层层封装之后,通过网卡,把数据发送出去。
这里使用的API是传输层提供的,传输层涉及到的紧张协议有两个:TCP和UDP
背面通过代码具体理解这些特点

   ①有/无连接:这里的“连接”是虚拟的,抽象的连接
  例:打电话——打已往对方接才能通话;微信发消息不管对面在不在线,消息都发出去了
  ②可/不可靠传输:可以知道数据到没到达对方
  ③面向字节省:传输数据的根本单位就是字节
  ④面向数据报:传输的的根本单位是一个“数据报”——由一系列字节构成的特定结构UDP
  ⑤全双工:可以双向通信
  ⑥半双工:只能单向通信
    客户端:发送哀求的一方,发送的数据叫做“哀求”
  服务器:被动担当哀求的一方,给客户端返回的数据叫做“相应”
  客户端和服务器之间的交互有这几种模式:“一问一答”,“一问多答”,“多问一答”,“多问多答”,
  二:UDP socket API使用

引入:UDP焦点类有两个DatagramSocket,DatagramPacket
1:socket文件

操作体系中有一类文件就叫做socket文件,区别于放在硬盘上的平常文件,socket文件是放在“网卡”这样的硬件设备上——通过网卡发送数据,就是写socket文件;担当数据,就是读socket文件
2:DatagramSocket类

(1)构造方法


(2)方法


3:DatagramPacket类

UDP面向数据报,每次发送和吸收数据的根本单位就是一个UDP数据报
(1)构造方法

(2)方法

三:回显服务器——服务器

1:引入(必看)

以下代码是实现一个“回显服务器”——是网络编程中的“hello world”,但是对新手小白并不友好
大抵流程为:客户端发出哀求,服务器收到客户端的哀求,完成业务并返反相应,客户端担当相应
先附赠上服务器的代码,(按照步调去边理解边敲)(重在理解,重在理解)
2:服务器相应代码

(1)注释版本

  1. package network;
  2. import java.io.IOException;
  3. import java.net.DatagramPacket;
  4. import java.net.DatagramSocket;
  5. import java.net.SocketException;
  6. /**
  7. * Created with IntelliJ IDEA.
  8. * Description:
  9. * User: Hua YY
  10. * Date: 2024-10-07
  11. * Time: 17:20
  12. */
  13. public class UdpEchoServer {
  14.     //1:创建DatagramSocket对象
  15.     private DatagramSocket socket = null;//socket:插槽插座
  16.     //2:构造方法,服务器一启动,就要关联/绑定上一个操作系统中的端口号(服务器的端口号哦啊通常由程序员指定)
  17.     //抛出的异常通常为scoket创建失败
  18.     public UdpEchoServer(int port) throws SocketException {
  19.         socket = new DatagramSocket(port);//端口号port
  20.     }
  21.     //3:服务器启动逻辑
  22.     //5:抛异常,网络编程socket本质上也是IO
  23.     public void start() throws IOException {
  24.         System.out.println("服务器启动");
  25.         while(true){
  26.             //3:创建一个数据报,它是每次发送数据和接收数据的一个基本单位
  27.             // 参数为输出型参数,字节数组,对应UDP的载荷部分,一开始是空的
  28.             DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
  29.             //4;socket读网卡能读到一个UDP数据报(里面会包含数据源IP,源端口),放到requestPacket(数据报)对象中
  30.             //如果没有接受到请求那么就会阻塞等待,此处收到的数据是先存到socket文件的内存缓冲区中。非硬盘
  31.             socket.receive(requestPacket);
  32.             //5:基于字节数组构造String对象,数组中的数据可能是文本数据(给String刚好)也可能是二进制数据(Java也能保存)
  33.             //这里的长度是有效长度
  34.             String request = new String(requestPacket.getData(),0,requestPacket.getLength());
  35.             //6:根据请求计算响应
  36.             String response = process(request);
  37.             //7:把响应(String)字节给拎出来,构造成一个DatagramPacket数据报,在传入socket对象(因为4中我们说过收到请求时,socket能读到源IP和源端口)
  38.             //这时我们把这个源IP和源端口,作为响应的目的IP和目的端口(确认客户端的发出请求的位置),返回回去
  39.             //注:response.length()单位是字符,此处单位是字节
  40.             DatagramPacket responsePacket = new DatagramPacket(response.getBytes() , response.getBytes().length , requestPacket.getSocketAddress());
  41.             socket.send(responsePacket);
  42.         }
  43.     }
  44.     //7:构造响应,这里是回显服务器,所以就是单纯的return
  45.     private String process(String request) {
  46.         return request;
  47.     }
  48. }
复制代码
(2)无注释版本

  1. package repeat2;
  2. import java.io.IOException;
  3. import java.net.DatagramPacket;
  4. import java.net.DatagramSocket;
  5. import java.net.SocketException;
  6. /**
  7. * Created with IntelliJ IDEA.
  8. * Description:
  9. * User: Hua YY
  10. * Date: 2024-10-10
  11. * Time: 18:28
  12. */
  13. public class UdpServer {
  14.     private DatagramSocket socket = null;
  15.     public UdpServer(int port) throws SocketException {
  16.         socket = new DatagramSocket(port);
  17.     }
  18.     public void start() throws IOException {
  19.         System.out.println("服务器启动");
  20.         while(true){
  21.             DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
  22.             socket.receive(requestPacket);
  23.             //转化为字符串
  24.             String request = new String(requestPacket.getData(),0,requestPacket.getLength());
  25.             String response = process(request);
  26.             DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
  27.                     requestPacket.getSocketAddress());
  28.             socket.send(responsePacket);
  29.             System.out.printf("[%s,%d]  request: %s  response: %s\n ",
  30.                     requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);
  31.         }
  32.     }
  33.     public String process(String request){
  34.         return request;
  35.     }
  36.     public static void main(String[] args) throws IOException {
  37.         UdpServer server = new UdpServer(9096);
  38.         server.start();
  39.     }
  40. }
复制代码

3:细节增补

这里在增补一些细节:
①创建完socket对象后,可以通过socket对象来操作网卡(具体:因为socket对象是在内存中的,针对这个内存对象进行操作就可以影响到网卡)
②构造方法(另有无参的上面有写)中的参数,是我们指定的,进程一启动就要绑定上操作体系中的端口号,这个端口号是一个整数,用来区分一个主机上的进行网络通信的差异程序
一个端口号只能被一个进程绑定,但是一个进程可以绑定多个端口号(像极了爱情~~,爱情中宁死不做端口号~~)

③SocketException,类似端口号被别的进程占用就会报非常
④因为服务器需要不停的运作,以是while一直循环
⑤数据报中的数组就是载荷部门

⑥receive有壅闭等待功能

⑧数据报的位置在socket对象的内存缓冲区中

⑨构造相应数据报
4:特点

上述代码可以体现出UDP是——
(1)无连接通信
UDP的DAtagramSocket自身并不需要保存对端的IP和端口,对端IP和端口在数据报中就已经包含,另外代码中也没有“建立连接”和“担当连接”这种操作
(2)不可靠数据——代码没体现(略)
(3)面向数据报
send方法和receive方法都是以DatagramPacket为根本单位的
(4)全双工
一个socket既可以发送数据报又可以担当数据报(属于是白手发迹了)
四:回显服务器——客户端

1:代码

(1)注释版本

  1. package network;
  2. import java.io.IOException;
  3. import java.net.*;
  4. import java.util.Scanner;
  5. /**
  6. * Created with IntelliJ IDEA.
  7. * Description:
  8. * User: Hua YY
  9. * Date: 2024-10-07
  10. * Time: 17:20
  11. */
  12. public class UdpEchoClient {
  13.     private DatagramSocket socket = null;
  14.     private String serverIp;
  15.     private int serverPort;
  16.     public UdpEchoClient(String serverIp , int serverPort) throws SocketException {
  17.         this.serverIp = serverIp;
  18.         this.serverPort = serverPort;
  19.         socket = new DatagramSocket();//传入参数为请求的目的ip和目的端口,源ip为本机ip源端口为系统分配的端口
  20.     }
  21.     public void start() throws IOException {
  22.         System.out.println("客户端启动");
  23.         Scanner scanner = new Scanner(System.in);
  24.         while(true){
  25.             System.out.print("->");
  26.             if (!scanner.hasNext()){//如果没有输入的话就结束循环
  27.                 break;
  28.             }
  29.             String request = scanner.next();//人为输入请求
  30.             DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,
  31.                     InetAddress.getByName(serverIp),serverPort);//指定服务器的ip和端口,分开的
  32.             socket.send(requestPacket);
  33.             DatagramPacket responsePacket = new DatagramPacket(new byte[4096] , 4096);
  34.             socket.receive(responsePacket);
  35.             //转化为字符串
  36.             String response = new String(responsePacket.getData(),0,responsePacket.getLength());//内置getLength()获取length成员变量
  37.             System.out.println(response);
  38.         }
  39.     }
  40.     public static void main(String[] args) throws IOException {
  41.         UdpEchoClient client = new UdpEchoClient("127.0.0.1",9090);
  42.         client.start();
  43.     }
  44. }
复制代码
(2)无注释版本

  1. package repeat2;
  2. import java.io.IOException;
  3. import java.net.*;
  4. import java.util.Scanner;
  5. /**
  6. * Created with IntelliJ IDEA.
  7. * Description:
  8. * User: Hua YY
  9. * Date: 2024-10-10
  10. * Time: 18:29
  11. */
  12. public class UdpEchoClient {
  13.     private DatagramSocket socket = null;
  14.     private String serverIp;
  15.     private int serverPort;
  16.     public UdpEchoClient(String serverIp , int serverPort) throws SocketException {
  17.         this.serverIp = serverIp;
  18.         this.serverPort = serverPort;
  19.         socket = new DatagramSocket();
  20.     }
  21.     public void start() throws IOException {
  22.         System.out.println("客户端启动");
  23.         Scanner scanner = new Scanner(System.in);
  24.         while(true){
  25.             System.out.print("->");
  26.             if(!scanner.hasNext()){
  27.                 break;
  28.             }
  29.             String request = scanner.next();
  30.             DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),
  31.                     request.getBytes().length, InetAddress.getByName(serverIp),serverPort);
  32.             socket.send(requestPacket);
  33.             //接收响应
  34.             DatagramPacket responsePacket = new DatagramPacket(new byte[4096] , 4096);
  35.             socket.receive(responsePacket);
  36.             String response = new String(responsePacket.getData(),0,responsePacket.getLength());
  37.             System.out.println(response);//
  38.         }
  39.     }
  40.     public static void main(String[] args) throws IOException {
  41.         UdpEchoClient client = new UdpEchoClient("127.0.0.1",9096);
  42.         client.start();
  43.     }
  44. }
复制代码
2:留意点

(1)服务器端口号需要手动指定是确保,客户端可以找到服务器,客户端的端口号是操作体系的内核随机分配的 (确保分配的端口号是空闲可用的)
   (2)Scanner从控制台读取字符串最好使用next非nextLine
  (如果是从文件读取就无所谓了)
  ①next读取
  

  
  

  ②nextLine读取
  

  (3).length和.length()方法的区别


五:回显服务器过程笔墨梳理


六:知识增补

1:.length和.length()的区别
引用文章java中length和length()的区别_length变量与length函数 java-CSDN博客

2:字符串转数组



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我爱普洱茶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表