socket的TCP和UDP样例

news2024/11/20 10:33:38

【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.coloradmin.cn/o/945695.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是ChatGPT水印,ChatGPT生成的内容如何不被检测出来,原理什么?

太长不看版 1. 什么是ChatGPT水印&#xff1f; ChatGPT水印是AI以伪随机方式生成的独特tokens序列。该序列用来作为水印&#xff0c;以区分AI生成内容和人类原创内容。 2. 如何规避ChatGPT水印&#xff1f; 一种规避方法是使用其他AI模型改写ChatGPT生成的文本。这会破坏水…

Nat. Mach. Intell 2020 | drugVQA+:准VAQ系统预测药物-蛋白质相互作用

论文标题&#xff1a;Predicting drug–protein interaction using quasi-visual question answering system 论文地址&#xff1a;Predicting drug–protein interaction using quasi-visual question answering system | Nature Machine Intelligence 代码&#xff1a;GitH…

继承AndroidView Model的错误

ViewModelProvider(this)[RegisterViewModel::class.java] 一行简单的代码&#xff0c;总是报这个错误 Caused by: java.lang.NoSuchMethodException: com.xinfa.registerlogin.viewmodel.LoginViewModel. [class android.app.Application] 经过一下午的思索&#xff0c;终于找…

科普:什么是DNS劫持?

DNS劫持又叫做域名劫持&#xff0c;指攻击者利用其他攻击手段&#xff0c;篡改了某个域名的解析结果&#xff0c;使得指向该域名的IP变成了另一个IP&#xff0c;导致对相应网址的访问被劫持到另一个不可达的或者假冒的网址&#xff0c;从而实现非法窃取用户信息或者破坏正常网络…

我们的第一个 Qt 窗口程序

Qt 入门实战教程&#xff08;目录&#xff09; Windows Qt 5.12.10下载与安装 为何使用Qt Creator开发QT 本文介绍用Qt自带的集成开发工具Qt Creator创建Qt默认的窗口程序。 本文不需要你另外安装Visual Studio 2022这样的集成开发环境&#xff0c;也不需要你再在Visual St…

【单片机】有人WH-LTE-7S1 4G cat1 模块连接服务器,教程,记录

文章目录 4G cat1 模块封装引脚名称功能拓扑图串口模块调试WH-LTE-7S1 4G cat1 模块 我买的这个模块内置了电信卡&#xff0c;不用插电话卡就能用&#xff0c;要插也行&#xff0c;在背面。 ⚫ 5-16V 宽电压供电 ⚫ LTE Cat 1&#xff0c;搭载 4G 网络&#xff0c;低时延&…

2023年腾讯云轻量应用服务器优缺点大全

2023年腾讯云轻量应用服务器优缺点大全&#xff0c;腾讯云轻量应用服务器性能如何&#xff1f;轻量服务器CPU内存带宽配置高&#xff0c;CPU采用什么型号主频多少&#xff1f;轻量应用服务器会不会比云服务器CVM性能差&#xff1f;腾讯云服务器网详解CPU型号主频、内存、公网带…

《存储IO路径》专题:IO虚拟化初探

大家好&#xff0c;欢迎来到今天的科技小课堂。今天我们要聊聊的是一项非常有趣且实用的技术——I/O虚拟化&#xff08;Input/Output Virtualization&#xff0c;简称IOV&#xff09;。想象一下&#xff0c;如果把物理硬件资源比作一道丰盛的大餐&#xff0c;那么IOV就是那位神…

Java 若依框架系统工具生成代码,前后端以及菜单添加使用示例

前言 若依框架不多介绍&#xff0c;目前比较流行的一款开源的后台管理框架&#xff0c;主要技术栈 后台spingboot、spingcloud 前端vue2 vue3版本的都有&#xff0c;可以去官方下载看看。 若依框架提供代码生成的功能&#xff0c;方便我们把简单的增删改查前后端代码生成直接…

【JAVA基础——JAVA8版本特性】

JAVA基础 版本特性 文章目录 JAVA基础Java8Lambda表达式lambda表达式类型 函数式接口接口默认方法与静态方法接口默认方法接口静态方法 方法引用OptionalStream流生产Stream Source的方式流的方法parallelStream流 Date/Time API其他特性重复注解扩展注解参数名字保留在字节码…

绿色能源迎来跨越式增长新时代

当今世界&#xff0c;百年未有之大变局加速演进&#xff0c;新一轮科技革命和产业变革深入发展&#xff0c;全球气候治理呈现新局面&#xff0c;新能源和信息技术紧密融合&#xff0c;生产生活方式加快转向低碳化、智能化&#xff0c;能源体系和发展模式正在进入非化石能源主导…

ROS中使用Navigation报错信息

在ROS中使用遇到了几个Navigation报错信息&#xff0c;在这里进行下记录&#xff1a; [ WARN] [1688134727.429227824]: The origin for the sensor at (7.35, 13.12) is out of map bounds. So, the costmap cannot raytrace for it. 解决办法&#xff1a; [ WARN] [16881…

flink on yarn with kerberos 边缘提交

flink on yarn 带kerberos 远程提交 实现 flink kerberos 配置 先使用ugi进行一次认证正常提交 import com.google.common.io.Files; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.flink.client.cli.CliFrontend; import o…

Gorilla LLM:连接海量 API 的大型语言模型

如果你对这篇文章感兴趣&#xff0c;而且你想要了解更多关于AI领域的实战技巧&#xff0c;可以关注「技术狂潮AI」公众号。在这里&#xff0c;你可以看到最新最热的AIGC领域的干货文章和案例实战教程。 一、前言 在当今这个数字化时代&#xff0c;大型语言模型&#xff08;LLM…

史上最全AP、mAP详解与代码实现

文章目录 前言一、mAP原理1、mAP概念2、准确率3、精确率4、召回率5、AP: Average Precision 二、mAP0.5与mAP0.5:0.951、mAP0.52、mAP0.5:0.95 三、mAP代码实现1、真实标签json文件格式2、模型预测标签json文件格式3、mAP代码实现4、mAP结果显示 四、模型集成mAP代码1、模型mai…

项目:点餐系统3mysql知识回顾MySQL客户端

连接数据库 mysql -uroot -p 密码&#xff1a;空 一、第三方库&#xff1a;MySQL 数据库-存储并管理数据的仓库&#xff0c;是一个C/S架构 MySQL客户端通过sql来告诉MySQL服务器&#xff0c;自己需要做什么操作 1.sql语句 sql&#xff1a;structure query language结构化查询…

LeetCode 44题:通配符匹配

题目 给你一个输入字符串 (s) 和一个字符模式 (p) &#xff0c;请你实现一个支持 ? 和 * 匹配规则的通配符匹配&#xff1a; ? 可以匹配任何单个字符。* 可以匹配任意字符序列&#xff08;包括空字符序列&#xff09;。 判定匹配成功的充要条件是&#xff1a;字符模式必须…

AI识别工人安全绳佩戴检测算法

AI识别工人安全绳佩戴检测算法通过yolov5智能图像识别算法对现场图像进行处理和分析&#xff0c;AI识别工人安全绳佩戴检测算法识别出工人是否佩戴安全绳&#xff0c;一旦发现工人未佩戴安全绳&#xff0c;AI识别工人安全绳佩戴检测算法将立即进行告警&#xff0c;并将事件记录…

SOLIDWORKS中多实体文件到装配体的转换技巧

我们在做机械等工程设计中&#xff0c;有时为了节省时间&#xff0c;需要把多实体的“零件”&#xff0c;直接转换为装配体&#xff0c;不再另外装配&#xff0c;这样能大大简化设计的操作时间&#xff0c;复杂程度。 在这里&#xff0c;我们首先要了解&#xff0c;SOLIDWORKS文…

2023常见前端面试题

以下是一些2023年秋招常见的前端面试题及其答案&#xff1a; 1. 请解释一下什么是前端开发&#xff1f; 前端开发是指使用HTML、CSS和JavaScript等技术来构建网页和用户界面的过程。前端开发人员负责将设计师提供的视觉设计转化为可交互的网页&#xff0c;并确保网页在不同设备…