socket的TCP和UDP样例

news/2024/5/18 12:07:37 标签: tcp/ip, udp, 单片机

【70天稳扎稳打学完JavaEE初阶】

        • TCP和UDP的区别及相关的不同应用
    • UDP实现回显功能
          • 一、UdpEchoServer服务器
          • 二、UdpEchoClient 客户端
          • 写一个 翻译服务器(继承服务器)
    • UDP示例二:展示服务器本地某个目录的下一级子文件列表服务
          • UDP服务器
          • UDP客户端
    • TCP示例一:一发一收(短连接)
            • TcpEchoClient 客户端
            • TcpEchoServer
    • TCP示例二:请求响应(短连接)
      • 服务器
      • 客户端

TCP和UDP的区别及相关的不同应用

在这里插入图片描述

UDP实现回显功能

一、UdpEchoServer服务器
package UdpEchoClient;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
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 {
        System.out.println("服务器启动!");
        while (true) {
            // 循环里面处理一次请求.
            // 1. 读取请求并解析
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);
            // 把这个 DatagramPacket 对象转成字符串, 方便去打印.
            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] req: %s; resp: %s\n", requestPacket.getAddress().toString(),
                    requestPacket.getPort(), request, response);
        }
    }

    // 当前写的是一个回显服务器.
    // 响应数据就和请求是一样的.
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}
二、UdpEchoClient 客户端
package UdpEchoClient;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class UdpEchoClient {
    private DatagramSocket socket = null;
    private String serverIP;
    private int serverPort;

    // 两个参数一会会在发送数据的时候用到.
    // 暂时先把这俩参数存起来, 以备后用.
    public UdpEchoClient(String serverIP, int serverPort) throws SocketException {
        // 这里并不是说就没有端口, 而是让系统自动指定一个空闲的端口~~
        socket = new DatagramSocket();
        // 假设 serverIP 是形如 1.2.3.4 这种点分十进制的表示方式 (关于点分十进制, 后面详细说)
        this.serverIP = serverIP;
        this.serverPort = serverPort;
    }

    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            // 1. 从控制台读取用户输入的内容.
            System.out.print("-> ");
            String request = scanner.next();
            // 2. 构造一个 UDP 请求, 发送给服务器.
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
                    InetAddress.getByName(this.serverIP), this.serverPort);
            socket.send(requestPacket);
            // 3. 从服务器读取 UDP 响应数据. 并解析
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePacket);
            String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
            // 4. 把服务器的响应显示到控制台上.
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);
        client.start();
    }
}
写一个 翻译服务器(继承服务器)
package UdpEchoClient;

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;

public class UdpTranslateServer extends UdpEchoServer {
    // 翻译是啥? 本质上就是 key -> value
    private Map<String, String> dict = new HashMap<>();

    public UdpTranslateServer(int port) throws SocketException {
        super(port);

        dict.put("cat", "小猫");
        dict.put("dog", "小狗");
        dict.put("fuck", "卧槽");
        // 在这里就可以填入很多很多的内容. 像有道这样的词典程序, 也就无非如此, 只不过这里有一个非常大的哈希表, 包含了几十万个单词.
    }

    // 重写 process 方法, 实现查询哈希表的操作
    @Override
    public String process(String request) {
        return dict.getOrDefault(request, "词在词典中未找到");
    }

    // start 方法和父类完全一样, 不用写了.

    public static void main(String[] args) throws IOException {
        UdpTranslateServer server = new UdpTranslateServer(9090);
        server.start();
    }
}

UDP示例二:展示服务器本地某个目录的下一级子文件列表服务

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

UDP服务器
import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.charset.StandardCharsets;

public class udpserver {

    //服务器socket要绑定固定的端口
    private static final int PORT = 8888;

    //本地文件目录要展示的根路径
    private static final String BASE_PATH = "E:/TMP";

    public static void main(String[] args) throws IOException {
        // 1.创建服务端Datagramsocket,指定端口,可以发送及接收UDP数据报
        DatagramSocket socket = new DatagramSocket(PORT);
        //不停的接收客户端udp数据报
        while (true) {
            byte[] requestData = new byte[1024];
            DatagramPacket requestPacket = new DatagramPacket(requestData,requestData.length);
            System.out.println("------------------------");
            System.out.println("等待接收UDP数据包...");
            socket.receive(requestPacket);
            System.out.printf("客户端IP:%s%n",requestPacket.getAddress().getHostAddress());
            System.out.printf("客户端端口号:%s%n",requestPacket.getPort());
            // 7.接收到的数据作为请求,根据请求数据执行业务,并返回响应
            for (int i = 0; i < requestData.length; i++) {
                byte b = requestData[i];
                if (b == '\3') {
                    String request = new String(requestData,0,i);
                    System.out.printf("客户端请求的文件列表路径为:%s%n",BASE_PATH+request);
                    File dir = new File((BASE_PATH + request));
                    File[] children = dir.listFiles();
                    StringBuilder response = new StringBuilder();
                    if (children != null) {
                        for (File child : children) {
                            response.append(child.getName() + "\n");
                        }
                    }
                    response.append("\3");
                    byte[] responseData = response.toString().getBytes(StandardCharsets.UTF_8);
                    DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length,requestPacket.getSocketAddress());
                    socket.send(responsePacket);
                    break;
                }
            }
        }
    }
}
UDP客户端
import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class udpserver {

    //服务端socket地址,包含域名或IP,及端口号
    private static final SocketAddress ADDRESS = new InetSocketAddress("1ocalhost",8888);

    public static void main(String[] args) throws IOException {
        // 4.创建客户端Datagramsocket,开启随机端口就行,可以发送及接收UDP数据报
        DatagramSocket socket = new DatagramSocket();

        //5-1.准备要发送的数据: 这里调整为键盘输入作为发送的内容
        Scanner scanner = new Scanner(System.in) ;
        while (true) {
            System.out.println("--------------------------");
            System.out.println("请输入要展示的目录");
            String request = scanner.nextLine() + "\3";
            byte[] requestData = request.getBytes(StandardCharsets.UTF_8);
            DatagramPacket requestPacket = new DatagramPacket(requestData,requestData.length,ADDRESS);
            socket.send(requestPacket);
            byte[] responseData = new byte[1024];
            DatagramPacket responsePacket = new DatagramPacket(responseData,responseData.length);
            socket.receive(responsePacket);
            System.out.println("该目录下的文件列表为:");
            int next = 0;
            for (int i = 0; i < responseData.length; i++) {
                byte b = responseData[i];
                if (b == '\3') {
                    break;
                }
                if (b == '\n') {
                    String fileName = new String(responseData, next, i-next);
                    System.out.println(fileName);
                    next = i+1;
                }
            }
        }
    }
}

TCP示例一:一发一收(短连接)

在这里插入图片描述

TcpEchoClient 客户端
package net_1013;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
    // 客户端需要使用这个 socket 对象来建立连接.
    private Socket socket = null;

    public TcpEchoClient(String serverIP, int serverPort) throws IOException {
        // 和服务器建立连接. 就需要知道服务器在哪了.
        // 这里和上节课写的 UDP 客户端差别较大了.
        socket = new Socket(serverIP, serverPort);
    }

    public void start() {
        Scanner scanner = new Scanner(System.in);
        try (InputStream inputStream = socket.getInputStream();
             OutputStream outputStream = socket.getOutputStream()) {
            while (true) {
                // 1. 从控制台读取数据, 构造成一个 请求
                System.out.print("-> ");
                String request = scanner.next();
                // 2. 发送请求给服务器
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(request);
                // 这个 flush 不要忘记. 否则可能导致请求没有真发出去.
                printWriter.flush();
                // 3. 从服务器读取响应
                Scanner respScanner = new Scanner(inputStream);
                String response = respScanner.next();
                // 4. 把响应显示到界面上
                System.out.println(response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);
        client.start();
    }
}
TcpEchoServer
package net_1013;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoServer {
    // 代码中会涉及到多个 socket 对象. 使用不同的名字来区分.
    private ServerSocket listenSocket = null;

    public TcpEchoServer(int port) throws IOException {
        listenSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动!");
        ExecutorService service = Executors.newCachedThreadPool();
        while (true) {
            // 1. 先调用 accept 来接受客户端的连接.
            Socket clientSocket = listenSocket.accept();
            // 2. 再处理这个连接. 这里应该要使用多线程. 每个客户端连上来都分配一个新的线程负责处理~
            //    此处使用多线程, 雀食能解决问题, 但是会导致频繁创建销毁多次线程!!
//            Thread t = new Thread(() -> {
//                try {
//                    processConnection(clientSocket);
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            });
//            t.start();

            service.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
        // 接下来就处理客户端的请求了.
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            while (true) {
                // 1. 读取请求并解析.
                Scanner scanner = new Scanner(inputStream);
                if (!scanner.hasNext()) {
                    // 读完了, 连接可以断开了.
                    System.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress().toString(),
                            clientSocket.getPort());
                    break;
                }
                String request = scanner.next();
                // 2. 根据请求计算响应
                String response = process(request);
                // 3. 把响应写回给客户端
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(response);
                // 刷新缓冲区确保数据确实是通过网卡发送出去了.
                printWriter.flush();

                System.out.printf("[%s:%d] req: %s; resp: %s\n", clientSocket.getInetAddress().toString(),
                        clientSocket.getPort(), request, response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 为啥这个地方要关闭 socket ? 而前面的 listenSocket 以及 udp 程序中的 socket 为啥就没 close??
            clientSocket.close();
        }
    }

    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }
}

TCP示例二:请求响应(短连接)

在这里插入图片描述

服务器

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

import static javax.servlet.http.MappingMatch.PATH;

class Tcpserver {
    //服务器socket要绑定固定的端口
    private static final int PORT = 8888;

    //本地文件目录要展示的根路径
    private static final String BASE_PATH = "E:/TMP";

    public static void main(String[] args) throws IOException {
        //1.创建一个服务端serversocket,用于收发TCP报文
        ServerSocket server = new ServerSocket(PORT);
        // 不停的等待客户端连接
        while (true) {
            System.out.println("-------------");
            System.out.println("等待客户端建立TCP连接...");
            Socket socket = server.accept();
            System.out.printf("客户端IP: %s%n",socket.getInetAddress().getHostAddress());
            System.out.printf("客户端端口号: %s%n",socket.getPort());
            //5.接收客户端的数据,需要从客户端socket中的输入流获取
            InputStream is = socket.getInputStream();
            //为了方便获取字符串 内容,可以将以上字节流包装为字符流
            BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
            //客户端请求只发送一行数据,我们也只需要读取一行
            String request = br.readLine();
            //6.根据请求处理业务:本地目录根路径+请求路径,作为要展示的目录,列出下一级子文件
            System.out.printf("客户端请求的文件列表路径为: %s%n",BASE_PATH + request);
            File dir = new File(BASE_PATH + request);
            File[] children = dir.listFiles();
            OutputStream os = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(os,"UTF-8"));
            if(children != null){
                for (File child : children) {
                    pw.println(child.getName());
                }
            }
            pw.flush() ;
            socket.close();
        }
    }


}

客户端

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

import static javax.servlet.http.MappingMatch.PATH;

class TcpClient {
    //服务端IP或域名
    private static final String SERVER_HOST = "localhost";
    //服务端socket进程的端口号
    private static final int SERVER_PORT = 8888;
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.println("---------------");
            System.out.println("请输入要展示的目录:");
            String request = scanner.nextLine();
            Socket socket = new Socket(SERVER_HOST,SERVER_PORT);
            OutputStream os = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(os,"UTF-8"));
            pw.println(request);
            pw.flush();
            System.out.println("接收到服务端响应:");
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line) ;
            }
            socket.close();
        }
    }
}

在这里插入图片描述


http://www.niftyadmin.cn/n/4982483.html

相关文章

关于商品活动的H5页面技术总结

背景 在单个html文件里面使用vue3、jquery等其他第三方js库&#xff0c;实现规定的页面效果&#xff0c;其中主要功能是从商品json数据中读取数据&#xff0c;然后可以通过搜索框、下拉框、左侧菜单来筛选商户信息。 页面布局 技术要点&#xff1a; 1、通过路由来进行页面布…

springcloud-gateway简述

Spring Cloud Gateway 是一个用于构建 API 网关的项目&#xff0c;它是 Spring Cloud 生态系统中的一部分&#xff0c;旨在为微服务架构提供动态路由、负载均衡、安全性和监控等功能。 网关工程对应pom文件 <?xml version"1.0" encoding"UTF-8"?>…

财务数据分析?奥威BI数据可视化工具很擅长

BI数据可视化工具通常是可以用户各行各业&#xff0c;用于不同主题的数据可视化分析&#xff0c;但面对财务数据分析这块难啃的骨头&#xff0c;能够好好地完成的&#xff0c;还真不多。接下来要介绍的这款BI数据可视化工具不仅拥有内存行列计算模型这样的智能财务指标计算功能…

【neo4j-python】安装与简单使用

文章目录 前言环境第一步&#xff1a;JDK安装第二步&#xff1a;neo4j安装第三步&#xff1a;测试neo4j是否安装成功第四步&#xff1a;Python进行连接neo4j 前言 最近新入坑梦幻模拟战手游&#xff0c;对于英雄的羁绊一直不是很清楚&#xff0c;也不知道怎么方便查找英雄的羁…

vue PDF或Word转换为HTML并保留原有样式

方法一 要将PDF或Word转换为HTML并保留原有样式&#xff0c;可以使用pdfjs-dist和mammoth.js这两个库。首先需要安装这两个库&#xff1a; npm install pdfjs-dist mammoth.js然后在Vue项目中使用这两个库进行转换&#xff1a; import * as pdfjsLib from pdfjs-dist; impor…

微信小程序使用stomp.js实现STOMP传输协议的实时聊天

简介&#xff1a; uniapp开发的小程序中使用 本来使用websocket&#xff0c;后端同事使用了stomp协议&#xff0c;导致前端也需要对应修改。 如何使用 在static/js中新建stomp.js和websocket.js&#xff0c;然后在需要使用的页面引入监听代码发送代码即可 代码如下&#x…

【论文阅读】你看不见我:对基于激光雷达的自动驾驶汽车驾驶框架的物理移除攻击

文章目录 AbstractIntroduction Abstract 自动驾驶汽车(AVs)越来越多地使用基于激光雷达的物体检测系统来感知道路上的其他车辆和行人。目前&#xff0c;针对基于激光雷达的自动驾驶架构的攻击主要集中在降低自动驾驶物体检测模型的置信度&#xff0c;以诱导障碍物误检测&…

uniapp如何应用onNeedPrivacyAuthorization实现微信小程序隐私政策

前言 微信小程序要求9.15日前实现隐私政策弹窗&#xff0c;但是uniapp文档一直没有更新&#xff0c;尝试直接使用wx.onNeedPrivacyAuthorization &#xff0c;是可以生效的 步骤 在 微信小程序后台 的 设置--服务内容与声明 &#xff0c;设置好小程序所需要的隐私政策在 uni…