TCP版本的 echo server 和 echo client

news2024/12/24 20:44:20

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • Tcp的api展示
  • 服务端
  • 客户端
  • 存在的问题
  • 解决问题
  • 服务端和客户端的大致流程


前言

上一篇文章我们介绍了UCP的客户端与服务器的一个简单实例,这篇我们简单的来介绍TCP版本的server和client的一个简单交互


Tcp的api展示

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

服务端

服务端的要做的流程
1.读取请求
2.根据请求计算响应
3.把响应写回给客户端

下面是完整代码

public class TpcEchoServer {
    //serverSocket就是外场拉课的小哥
    //clientSocket就是内场服务的小姐姐
    //serverSocket只有一个,clientSocket会给每个客户分配一个
    private ServerSocket serverSocket = null;

    public TpcEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    //启动过程
    public void start() throws IOException {
        System.out.println("服务器启动");
        ExecutorService executorService = Executors.newCachedThreadPool();
        //因为我们服务器要反复读取一个服务,所以我们要使用循环
        while (true) {
            Socket clientSocket = serverSocket.accept();
            processConnection(clientSocket);

    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress().toString(),
                clientSocket.getPort());
        //try()这种写法种,允许写多个流对象.使用;来分割
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            //我们使用prinwriter把字节流包装秤字符流
            Scanner scanner = new Scanner(inputStream);
            PrintWriter printWriter = new PrintWriter(outputStream);
            while (true) {
                //1.读取请求
                if (!scanner.hasNext()) {
                    //读到流的结尾了.
                    System.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress().toString(),
                            clientSocket.getPort());
                    break;
                }
                //直接使用scanner读取一段字符串
                String request = scanner.next();
                //2.根据请求计算响应
                String response = process(request);
                //3.把响应写回给客户端
                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 {
            clientSocket.close();
        }
    }

    public String process(String request) {
        return request;
    }
    public static void main(String[] args) throws IOException {
        TpcEchoServer tcpEchoServer = new TpcEchoServer(9090);
        tcpEchoServer.start();
    }
}

我针对几个方法具体解释一下.

  private ServerSocket serverSocket = null;
  Socket clientSocket = serverSocket.accept();
  

在这里插入图片描述
处理代码代码的解释:
在这里插入图片描述

客户端

客户端的一个流程
1.从键盘上读取用户输入内容
2.讲读取的内容放给服务器
3.从服务器读取响应内容
4.把响应内容显示在控制台上

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 {
    private Socket socket = null;

    public TcpEchoClient(String serverIp, int port) throws IOException {
        //这个操作相当于让客户端和服务器建立tcp连接.
        //这里连接上了,socket就会返回
        socket = new Socket(serverIp, port);
    }

    //开始启动客户端
    public void start() {
        Scanner scanner = new Scanner(System.in);
        try (InputStream inputStream = socket.getInputStream();
             OutputStream outputStream = socket.getOutputStream())
        { PrintWriter printWriter = new PrintWriter(outputStream);
            Scanner scannerFromSocket = new Scanner(inputStream);
            while (true){
                //1.从键盘上读取用户输入内容
                System.out.println("->");
                String request= scanner.next();
                //2.讲读取的内容放给服务器
                printWriter.println(request);
                printWriter.flush();
                //3.从服务器读取响应内容
                String response=scannerFromSocket.next();
                //4.把响应内容显示在控制台上
                System.out.printf("req: %s; resp: %s\n", request, response);

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

存在的问题

这里其实存在一个问题,就是当我们多个客户端去访问服务器的时候,服务端要处理完第一个客户端,在处理第二个客户端,具体看下图.
在这里插入图片描述

解决问题

先来看看我们针对服务端的处理客户端的请求代码

  public void start() throws IOException {
        System.out.println("服务器启动");
        ExecutorService executorService = Executors.newCachedThreadPool();
        //因为我们服务器要反复读取一个服务,所以我们要使用循环
        while (true) {
            Socket clientSocket = serverSocket.accept();
            processConnection(clientSocket);
        }
    }

改造后的代码
在这里插入图片描述

  public void start() throws IOException {
        System.out.println("服务器启动");
        ExecutorService executorService = Executors.newCachedThreadPool();
        //因为我们服务器要反复读取一个服务,所以我们要使用循环
        while (true) {
            Socket clientSocket = serverSocket.accept();
            Thread t = new Thread(() -> {
                try {
                    processConnection(clientSocket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }

服务端和客户端的大致流程

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/432506.html

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

相关文章

111.【金橘社区1.0】

金橘社区1.0版本 (一)、SpringBoot整合SpringSecurity1.导入依赖2.数据库3.登入表单4. 添加配置类 SecurityConfig5.接口实现类 CkqnUserServiceImpl6.前端认证问题 (二)、SpringBoot整合Ajax1.登入表单2. JavaScript (三)、SpringBoot整合editor.md1.编写页面(1).前端页面(2).…

Windows安装RedisJSON(无需编译)

文章目录 Windows安装RedisJSON下载解压配置文件启动服务启动客户端 Windows安装RedisJSON 下载 打开网址 https://github.com/zkteco-home/RedisJson。 在网页的右上角,点击“Code”按钮,然后选择“Download ZIP”以下载最新版本的RedisJSON。 网盘 …

C6678-控制GPIO输入/输出

C6678-控制GPIO输入/输出 术语寄存器起始地址原理输入输出测试中断功能原理中断原理框图芯片中断控制器原理框图内核中断控制器原理框图中断路由架构一级中断表二级中断表CIC0二级中断CIC1二级中断CIC2二级中断CIC3 中断演示代码参考资料 术语 NMI: 不可屏蔽中断CI…

6、在vscode上利用cmake创建第一个简单C++程序

文章目录 (1)前期准备工作:即安装对应的环境1)在vscode上安装插件:C/C、Cmake、CMake tools2)安装Cmake环境(这是在前面博客提到的已经安装好gcc等环境的前提下进行的) (…

Springboot基础学习之(二十二):异步任务和邮件任务

方向一:高效学习方法分享 我认为学习的最好的办法就是做笔记:本人特别喜欢在网上学习一些课堂外的知识,但是如果你没有及时的复习,要想找到自己想要的知识该怎么办呢?对,就是做笔记我在csdn这个app发的所有内容都是笔记…

Android UI布局优化之include、merge与ViewStub标签的巧用方法

前言 在开发中UI布局是我们都会遇到的问题,随着UI越来越多,布局的重复性、复杂度也会随之增长。 相信大家经常听到include、merge、ViewStub这样的标签,官方也提到这三种布局可用于布局的优化。今天就介绍下这三种布局的使用,记…

SRv6项目实践(一):环境与工具介绍

在一切开始之前,首先介绍一下我们要做什么,做这个要有什么基础,以及实现的环境 1,实验目标与实验基础 我们要在图下图所示的拓扑中,完成在如以下拓扑所示的网络中,配合ONOS实现基本的L2L3转发以及SRv6&am…

港联证券|券商再迎利好!这一比例大幅下调,释放300亿资金

券商利好接二连三。 4月10日,即日起下调证券公司转融通保证金份额。资信优质的公司,保证金份额由20%下调至5%;资信杰出的公司,由20%下调至10%;其余公司由25%下调至15%。中证金融预计,保证金份额下调后&…

Linux系统之tomcat的安装方法

Linux系统之tomcat的安装方法一、tomcat介绍1.tomcat简介2.tomcat官网二、本次环境规划三、安装jdk1.下载jdk包2.安装jdk3.检查jdk版本四、安装tomcat1.下载tomcat2.解压tomcat软件包3.设置环境变量4.查看tomcat版本五、启动tomcat1.启动tomcat服务2.检查tomcat服务状态3.访问t…

原来情感可以这样影响用户体验设计

🔥情绪的基本情况 Emotion:即刻的生理反应, Feeling:物理的或者心理上的,是emotion经过思考后的 Mood:持续时间更长,是一种状态,受到很多因素影响(天气、睡眠&#x…

92-TCP三次握手及TCP四次挥手

TCP三次握手及TCP四次挥手1.tcp三次握手(1)tcp的特点(2)tcp三次握手发生在什么阶段(3)tcp协议报头(4)tcp三次握手的流程2.tcp四次挥手(1)tcp四次挥手发生在什么阶段(2)tcp四次挥手的流程(3)能不能将服务器发端发送的ACK和FIN放在一起发送呢1.tcp三次握手 (1)tcp的特点 TCP 协…

十六、市场活动:查看市场活动明细(二)

功能需求 点击市场活动名称链接,跳转到明细页面,查看市场活动明细 -市场活动的基本信息 -市场活动下所有的备注信息 功能分析 流程图 代码实现 一、ActivityRemarkMapper 1.ActivityRemarkMapper接口 /*** 根据市场活动id查询备注*/List<ActivityRemark> selectActivi…

贪吃蛇小项目

1.总体程序 #include <curses.h> #include <stdlib.h> #include <pthread.h> #include <math.h> #include <time.h> struct Snake //贪吃蛇身子节点 {char node; //节点序号int row; //行坐标int column; //列坐标stru…

探索实践低光照场景下YOLOv5s模型上限,融合CBAM注意力机制开发构建基于改进YOLOv5s的低光照条件下目标检测识别分析系统

在现实生活场景里面&#xff0c;很多场景下光线光照条件都是比较差的&#xff0c;比如夜晚、室内等&#xff0c;这时候以往的目标检测模型是否还能够胜任我们所需的目标检测任务呢&#xff1f;这里主要的想法就是基于地光线条件下的数据集来开发构建目标检测系统&#xff0c;探…

Flowable6.x导出/查看/跟踪流程图(续)

书接上回 项目源码仓库 无论是待办、已办&#xff0c;亦或是流转中、已结束的流程实例&#xff0c;通过使用JS绘制SVG格式的交互式流程图&#xff0c;与以上篇博文中三种方式相比&#xff0c;在效果上都具有明显优势。 运行效果如下图所示&#xff1a; 整合、改造Flowable中…

110.【23种设计模式--创建者模式】

Java 23种设计模式 (一)、设计模式相关内容介绍1.软件设计模式概述(1).软件设计模式的产生背景(2).软件设计模式的概念(3).学习设计模式的重要性(4).设计模式分类 2.UML图(1).类图概述(2).类图的作用(3).类图表示法 3.软件设计原则(1).开闭原则 (重写不修改)(2).里氏代换原则 (…

node的安装与卸载

node的安装与卸载 今天遇到个问题 使用npm命令时报错显示栈溢出&#xff0c;所以将node重装了一下&#xff0c; 一.卸载node&#xff1a; 1.在程序与功能里卸载node.js&#xff0c;然后删除node相关文件夹&#xff0c;此次安装我将node安装在C盘里&#xff0c;将他的全局缓存…

10万字信用大数据一体化监管平台建设方案word

本资料来源公开网络&#xff0c;仅供个人学习&#xff0c;请勿商用&#xff0c;如有侵权请联系删除。 1.1、 系统主要功能需求分析 XX公共信用信息管理系统的主要业务流程包括信用信息资源编录管理流程、信用信息归集流程、信用信息服务流程和信用信息异议处理流程。 一.1.1…

NLP作业01:利用HMM实现词性标注

作业头 这个作业属于哪个课程自然语言处理这个作业要求在哪里利用HMM实现词性标注作业要求我在这个课程的目标实现词性标注这个作业在哪个具体方面帮助我实现目标代码实现参考文献1.隐马尔科夫模型 2.基于HMM的词性标注  3.基于HMMViterbi算法的词性标注 Python 文章目录 作…

【LeetCode: 673. 最长递增子序列的个数 | 动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…