java案例-服务端与客户端(传输对象)

news/2024/5/15 5:17:30

需求

在这里插入图片描述

代码

  • SysUser 用户类
  • Operation 操作类
  • Client 客户端
  • Server 服务端
  • ServerReaderThread 服务端线程类

SysUser 用户类

  • 需要实现Serializable 方便序列化,传输对象
public class SysUser implements Serializable {private String username;private String password;public SysUser() {}public SysUser(String username, String password) {this.username = username;this.password = password;}public String getUsername() {return this.username;}public String getPassword() {return this.password;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "SysUser{" +"username='" + username + '\'' +", password='" + password + '\'' +'}';}
}

操作类

操作方法和被操作的用户

public class Operation implements Serializable {private String operation;private SysUser sysUser;public Operation() {}public Operation(String operation, SysUser sysUser) {this.operation = operation;this.sysUser = sysUser;}public String getOperation() {return this.operation;}public SysUser getSysUser() {return this.sysUser;}public void setOperation(String operation) {this.operation = operation;}public void setSysUser(SysUser sysUser) {this.sysUser = sysUser;}@Overridepublic String toString() {return "Operation{" +"operation='" + operation + '\'' +", sysUser=" + sysUser +'}';}
}

客户端

  • 本例是一个长连接:一直挂在服务器端,那么服务器端的读取线程中就必须要有一个while 循环 不断读取此长连接的内容
  • 如果不使用本例的方法,而是每次都创建新的socket 连接服务器,那么读取线程中就必须要有一个while 循环就是非必要的,因为每次连接只会发送一次,等待服务器端响应之后,需要关闭此socket,这就是短连接
// 该类是一个客户端类
public class Client {private static Scanner scanner = new Scanner(System.in);public static void main(String[] args) throws IOException {start();}// 该方法是一个启动方法public static void start() throws IOException {Scanner scanner = new Scanner(System.in);Socket socket = new Socket("127.0.0.1",8888);// 此处加死循环 是为了让客户端一直运行while (true){System.out.println("请输入你要进行的操作");System.out.println("1.注册");System.out.println("2.登录");System.out.println("3.退出");String i = scanner.next();switch (i){case "1":System.out.println("注册");register(socket);break;case "2":System.out.println("登录");login(socket);break;case "3":System.out.println("退出");socket.close();break;default:System.out.println("输入错误,请重新输入");}}}// 该方法是一个注册方法public static void register(Socket socket) throws IOException {System.out.println("请输入用户名");String username = scanner.next();System.out.println("请输入密码");String password = scanner.next();SysUser sysUser = new SysUser(username,password);Operation operation = new Operation("register",sysUser);// 获取输出流requestAndRespond(socket, operation);}private static void requestAndRespond(Socket socket, Operation operation) throws IOException {OutputStream outputStream = socket.getOutputStream();// 封装输出流为对象输出流ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);// 写出对象objectOutputStream.writeObject(operation);objectOutputStream.flush();// 不要关闭流 否则会关闭socket//objectOutputStream.close();// 获取响应InputStream inputStream = socket.getInputStream();DataInputStream dataInputStream = new DataInputStream(inputStream);String response = dataInputStream.readUTF();System.out.println(response);}// 该方法是一个登录方法public static void login(Socket socket) throws IOException {System.out.println("请输入用户名");String username = scanner.next();System.out.println("请输入密码");String password = scanner.next();SysUser sysUser = new SysUser(username,password);Operation operation = new Operation("login",sysUser);// 获取输出流requestAndRespond(socket, operation);}
}

服务器端

// 该类是一个服务端类
public class Server {// 模拟数据库public static final File file = new File("test999.txt");public static ServerSocket serverSocket;//  创建线程池public static final ExecutorService pool =  new ThreadPoolExecutor(3, 5, 8, TimeUnit.SECONDS,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());static {try {serverSocket = new ServerSocket(8888);} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException {start();}// 该方法是一个启动方法public static void start() throws IOException {System.out.println("服务端启动");listen();}public static void listen() throws IOException {System.out.println("监听中");// 此处加死循环 是为了让服务器已知监听有没有客户端连接while (true){// 获取客户端的socketSocket socket = serverSocket.accept();// 使用线程池执行线程pool.execute(new ServerReaderThread(socket));}}// 该方法是一个注册方法public static void register(SysUser sysUser,Socket socket) throws IOException, ClassNotFoundException {System.out.println("注册");// 获取数据库中的所有用户FileInputStream fileInputStream = new FileInputStream(file);if (fileInputStream.available() > 0) {ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);ArrayList<SysUser> sysUsers = (ArrayList<SysUser>) objectInputStream.readObject();for (SysUser user : sysUsers) {if (user.getUsername().equals(sysUser.getUsername())) {System.out.println("用户名已存在");OutputStream outputStream = socket.getOutputStream();DataOutputStream dataOutputStream = new DataOutputStream(outputStream);dataOutputStream.writeUTF("用户名已存在");dataOutputStream.flush();
//                    dataOutputStream.close();return;}}}// 注册用户// 将用户写入数据库 追加模式FileOutputStream fileOutputStream = new FileOutputStream(file,true);ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);ArrayList<SysUser> sysUsersRegister = new ArrayList<>();sysUsersRegister.add(sysUser);objectOutputStream.writeObject(sysUsersRegister);System.out.println("注册成功");System.out.println(sysUser);OutputStream outputStream = socket.getOutputStream();DataOutputStream dataOutputStream = new DataOutputStream(outputStream);dataOutputStream.writeUTF("注册成功");dataOutputStream.flush();
//        dataOutputStream.close();}// 该方法是一个登录方法public static void login(SysUser sysUser,Socket socket) throws IOException, ClassNotFoundException {System.out.println("登录");// 获取数据库中的所有用户FileInputStream fileInputStream = new FileInputStream(file);if (fileInputStream.available() > 0) {ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);ArrayList<SysUser> sysUsers = (ArrayList<SysUser>) objectInputStream.readObject();for (SysUser user : sysUsers) {if (user.getUsername().equals(sysUser.getUsername())&&user.getPassword().equals(sysUser.getPassword())) {System.out.println("登录成功");System.out.println(sysUser);OutputStream outputStream = socket.getOutputStream();DataOutputStream dataOutputStream = new DataOutputStream(outputStream);dataOutputStream.writeUTF("登录成功");dataOutputStream.flush();
//                    dataOutputStream.close();}else {System.out.println("用户名或密码错误");OutputStream outputStream = socket.getOutputStream();DataOutputStream dataOutputStream = new DataOutputStream(outputStream);dataOutputStream.writeUTF("用户名或密码错误");dataOutputStream.flush();
//                    dataOutputStream.close();}}}else {System.out.println("数据库中没有用户");OutputStream outputStream = socket.getOutputStream();DataOutputStream dataOutputStream = new DataOutputStream(outputStream);dataOutputStream.writeUTF("数据库中没有用户");dataOutputStream.flush();
//            dataOutputStream.close();}}
}

服务器端读取类

  • 本例是一个长连接:一直挂在服务器端,那么服务器端的读取线程中就必须要有一个while 循环 不断读取此长连接的内容
  • 如果不使用本例的方法,而是每次都创建新的socket 连接服务器,那么读取线程中就必须要有一个while 循环就是非必要的,因为每次连接只会发送一次,等待服务器端响应之后,需要关闭此socket,这就是短连接
ServerReaderThread extends Thread {private Socket socket;public ServerReaderThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {// 最开始这个地方没有死循环,导致客户端只能发送一次请求// 这个地方加入死循环 是为了即使是一个request也能一直获得用户的输入// 这个地方如果不加入死循环,那么应该建立短连接// 也就是说,客户端发送一个请求,都会建立一个新的socket,服务端处理完这个请求之后,返回给客户端结果,客户端处理完结果之后,关闭socketwhile(true){// 获取输入流InputStream inputStream = socket.getInputStream();// 封装输入流为对象输入流ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);// 读取对象Operation operation = (Operation) objectInputStream.readObject();// 获取操作String operation1 = operation.getOperation();// 获取用户SysUser sysUser = operation.getSysUser();System.out.println("线程方法");switch (operation1) {case "register":register(sysUser,socket);break;case "login":login(sysUser,socket);break;default:break;}}} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}
}

http://www.mrgr.cn/p/00845044

相关文章

《面向云计算的零信任体系第1部分:总体架构》行业标准正式发布

中华人民共和国工业和信息化部公告2024年第4号文件正式发布行业标准&#xff1a;YD/T 4598.1-2024《面向云计算的零信任体系 第1部分&#xff1a;总体架构》&#xff08;后简称“总体架构”&#xff09;&#xff0c;并于2024年7月1日正式施行。 该标准由中国信通院牵头&#xf…

蓝桥杯ctf2024 部分wp

数据分析 1. packet 密码破解 1. cc 逆向分析 1. 欢乐时光 XXTEA #include<stdio.h> #include<stdint.h> #define DELTA 0x9e3779b9 #define MX (((z>>5^y<<2)(y>>3^z<<4))^((sum^y)(key[(p&3)^e]^z))) void btea(unsigned int* v…

工业异常检测

工业异常检测在业界和学界都一直是热门&#xff0c;近期其更是迎来了全新突破&#xff1a;与大模型相结合&#xff01;让异常检测变得更快更准更简单&#xff01; 比如模型AnomalyGPT&#xff0c;它克服了以往的局限&#xff0c;能够让大模型充分理解工业场景图像&#xff0c;判…

常用算法代码模板 (3) :搜索与图论

AcWing算法基础课笔记与常用算法模板 (3) ——搜索与图论 常用算法代码模板 (1) &#xff1a;基础算法 常用算法代码模板 (2) &#xff1a;数据结构 常用算法代码模板 (3) &#xff1a;搜索与图论 常用算法代码模板 (4) &#xff1a;数学知识 文章目录 0 搜索技巧1 树与图的存…

OpenHarmony 项目实战:智能体重秤

一、简介 本 demo 基于 OpenHarmony3.1Beta 版本开发&#xff0c;该样例能够接入数字管家应用&#xff0c;通过数字管家应用监测体重秤上报数据&#xff0c;获得当前测量到的体重&#xff0c;身高&#xff0c;并在应用端形成一段时间内记录的体重值&#xff0c;以折线图的形式…

在 UOS 统信安装 dotnet sdk 失败 提示 failed the verification

在 UOS 统信安装 dotnet sdk 失败 提示 You cannot install /home/lindexi/packages-microsoft-prod.deb that failed the verification, please go to Security Center - Security Tools - Application Security to adjust这是群里的伙伴报告的问题,从错误提示看需要在安全工…

制作一个能构建 dotnet AOT 的 gitlab ruuner 的 Debian docker 镜像

我的需求是需要有一个能够构建出 dotnet 的 AOT 包的环境,要求这个环境能解决 glibc 兼容依赖的问题,能打出来 x64 和 arm64 的 AOT 的包,且能够运行 gitlab runner 对接自动构建需求 以下是我列举的需求支持制作能在 UOS 系统和麒麟系统上运行的包 支持制作出来的包是 AOT …

个人学习总结__打开摄像头、播放网络视频的以及ffmpeg推流

前言 最近入手了一款非常便宜的usb摄像头&#xff08;买回来感觉画质很低&#xff0c;没有描述的4k&#xff0c;不过也够用于学习了&#xff09;,想着利用它来开启流媒体相关技术的学习。第一步便是打开摄像头&#xff0c;从而才能够对它进行一系列后续操作&#xff0c;诸如实…

将要上市的自动驾驶新书《自动驾驶系统开发》中摘录片段

全书共分15章&#xff1a;第1章是自动驾驶系统的概述&#xff08;场景分类、开发路径和数据闭环等&#xff09;&#xff0c;第2章简介自动驾驶的基础理论&#xff0c;即计算机视觉和深度学习等&#xff0c;第3&#xff5e;4章是自动驾驶的软硬件平台分析&#xff0c;包括传感器…

【PyTorch与深度学习】2、PyTorch张量的运算API(上)

课程地址 最近做实验发现自己还是基础框架上掌握得不好&#xff0c;于是开始重学一遍PyTorch框架&#xff0c;这个是课程笔记&#xff0c;这个课还是讲的简略&#xff0c;我半小时的课听了一个半小时。 1. 张量 1.1 张量操作 &#xff08;1&#xff09;chunk&#xff1a;将一…

Web前端开发之CSS_2

关系选择器CSS盒子模型弹性盒子模型文档流浮动清除浮动定位 1. 关系选择器 1.1 后代选择器 E F{} 选择所有被 E 元素包含的 F 元素&#xff0c;中间用空格隔开 <ul> <li>后代列表1</li> <div> <ol> <li>后代列表2</li> </ol>…

Vue从入门到精通-01-Vue的介绍和vue-cli

MVVM模式 Model&#xff1a;负责数据存储 View&#xff1a;负责页面展示 View Model&#xff1a;负责业务逻辑处理&#xff08;比如Ajax请求等&#xff09;&#xff0c;对数据进行加工后交给视图展示 关于框架 为什么要学习流行框架 1、企业为了提高开发效率&#xff1a;…

linux的压缩与备份

一、打包 格式&#xff1a;tar -参数 <打包文件名> <打包的目标> 作用&#xff1a;将文件或者目录打包 重要参数&#xff1a;-f 使用归档文件&#xff0c;一定要加上这个参数 -c 新建打包文件 -x 解包文件 -t 可以不用解包就能查看包文件内容 -v 打包和解包时显…

读天才与算法:人脑与AI的数学思维笔记13_Coq证明助手

读天才与算法:人脑与AI的数学思维笔记13_Coq证明助手1. 计算机 1.1. 对于计算机来说,它就很擅长处理这种重复而机械且计算量庞大的任务 1.1.1. 在速度与准确性等方面,计算机是远超过手工计算的 1.2. 计算机只能执行指令,并无自主创造力 1.…

Android --- 常见UI组件

TextView 文本视图 设置字体大小&#xff1a;android:textSize"20sp" 用sp 设置颜色&#xff1a;android:textColor"#00ffff" 设置倍距(行距)&#xff1a;android:lineSpacingMultiplier"2" 设置具体行距&#xff1a;android:lineSpacingExtra&q…

学习STM32第二十天

低功耗编程 一、修改主频 STM32F4xx系列主频为168MHz&#xff0c;当板载8MHz晶振时&#xff0c;系统时钟HCLK满足公式 H C L K H S E P L L N P L L M P L L P HCLK \frac{HSE \times PLLN}{PLLM \times PLLP} HCLKPLLMPLLPHSEPLLN​&#xff0c;在文件stm32f4xx.h中可修…

Django初步了解

目录 一、什么是Django 二、Django的设计模式 三、涉及的英文缩写及其含义 四、安装&#xff08;官方教程&#xff09; 一、什么是Django Django是一个Python Web框架&#xff0c;可以快速开发网站&#xff0c;提供一站式的解决方案&#xff0c;包括缓存、数据库ORM、后台…

甘特图是什么?利用甘特图来优化项目管理流程

在现代项目管理中,图表是一种强大而直观的工具,可以帮助项目经理和团队成员清晰地了解并掌控整个项目进程。其中,甘特图是最常用和最有效的图表之一。 甘特图是一种条形图,可以用来直观地展示项目中各个任务的进度、持续时间和相互关系。它由一个横轴和一个纵轴组成。横轴代表时…

STM32入门_江协科技_1~2_OB记录的自学笔记_STM32简介

1.综述 1.1. 课程简介 手打代码是加入了实操&#xff0c;增加学习效果&#xff1b; STM最小系统板面包板的硬件平台&#xff1b; 配套0.96寸的显示屏&#xff0c;便于调试&#xff1b; 因为使用面板板&#xff0c;所以如果程序现象不出来也有可能是硬件连接的问题&#xff1b; …

YOLOv8改进项目汇总-超全改进-ultralyticsPro介绍:订阅了《芒果YOLOv8原创改进专栏》的读者免费赠送,包括很多稀有改进

&#x1f525;&#x1f525;&#x1f525;专注于YOLOv8改进&#xff0c;NEW - YOLOv8 &#x1f680; in PyTorch >, Support to improve Backbone, Neck, Head, Loss, IoU, LA, NMS and other modules&#x1f680; Makes YOLOv8 improvements easy again 芒果出品 YOLOv8…