Java 网络编程之TCP(二):基于BIO的聊天室

embedded/2024/9/18 21:12:37/ 标签: java, BIO, 聊天室

在上一篇【Java 网络编程之TCP(一):基于BIO】中,介绍Java中I/O和TCP的基本概念,本文在上文的基础上,实现一个基本的聊天室的功能。

聊天室需求描述:

聊天客户端:发送消息给所有其他客户端,接收其他客户端的消息

实现说明:

要想实现上面的聊天室的功能,我们需要一个服务端,和客户端

服务端:接收客户端的消息,并转发给其他客户端

客户端:发送消息给服务端,接收服务端的消息

由于基于BIO,那么服务端都需要用两个线程,来分别进行收发消息

代码如下:

服务端:

java">import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;/*** 基于BIO的TCP网络通信的服务端,可以接收多个客户端连接,通过字节流接收客户端发送的消息;* 并发每个客户端的数据,转发给其余所有的客户端* 一个客户端需要使用一个线程* todo:线程资源复用; 字符流readLine 没有换行符阻塞的问题** @author freddy*/
class ChatServer {// 存放所有和服务端建立连接的客户端,客户端断开,需要去除public static List<Socket> clients = new LinkedList<>();public static void main(String[] args) throws IOException {// 开启server 监听端口ServerSocket serverSocket = new ServerSocket(9999);while (true) {Socket client = serverSocket.accept(); // 阻塞操作,需要新的线程处理客户端// 客户端保存,方便后面转发数据clients.add(client);// 接收Client数据,并转发new Thread(new ServerThread(client, clients)).start();}}
}/*** 服务端的线程,一个客户端对应一个*/
class ServerThread implements Runnable {Socket socket;List<Socket> clients;public ServerThread(Socket socket, List<Socket> clients) {this.socket = socket;this.clients = clients;}@Overridepublic void run() {// 获取输入流程,读取用户输入// 持续接收Client数据,并打印System.out.println("server had a client" + socket);try (InputStream inputStream = socket.getInputStream()) {byte[] buffer = new byte[1024];int len;// read操作阻塞,直到有数据可读// -1 表示流关闭,或者读到文件末尾while ((len = inputStream.read(buffer)) != -1) {System.out.println("serer receive data from " + socket + " : " + new String(buffer, 0, len));// 转发数据到其他Clientfor (Socket client : clients) {if (client != socket) {client.getOutputStream().write(new String(buffer, 0, len).getBytes());}}}} catch (IOException e) {System.out.println(socket + " disconnect ");// 去除当前clientclients.remove(socket);}}
}

客户端代码:

java">import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;/*** 基于BIO的TCP网络通信的客户端,接收控制台输入的数据,然后通过字节流发送给服务端** @author freddy*/
class ChatClient {public static void main(String[] args) throws IOException {// 连接serverSocket serverSocket = new Socket("localhost", 9999);System.out.println("client connected to server");// 读取用户在控制台上的输入,并发送给服务器new Thread(new ClientThread(serverSocket)).start();// 接收服务端发送过来的数据try (InputStream serverSocketInputStream = serverSocket.getInputStream();) {byte[] buffer = new byte[1024];int len;while ((len = serverSocketInputStream.read(buffer)) != -1) {System.out.println("client receive data from server" + serverSocketInputStream + " : " + new String(buffer, 0, len));}}}
}class ClientThread implements Runnable {private Socket serverSocket;public ClientThread(Socket serverSocket) {this.serverSocket = serverSocket;}@Overridepublic void run() {// 读取用户在控制台上的输入,并发送给服务器InputStream in = System.in;byte[] buffer = new byte[1024];int len;try (OutputStream outputStream = serverSocket.getOutputStream();) {// read操作阻塞,直到有数据可读,由于后面还要接收服务端转发过来的数据,这两个操作都是阻塞的,所以需要两个线程while ((len = in.read(buffer)) != -1) {System.out.println("client receive data from console" + in + " : " + new String(buffer, 0, len));// 发送数据给服务器端outputStream.write(new String(buffer, 0, len).getBytes()); // 此时buffer中是有换行符}} catch (IOException e) {throw new RuntimeException(e);}}
}

测试:

先开启服务端,再开启两个客户端,在客户端1的控制台发送i'm client1,在客户端1的控制台发送this is client2,通过日志可以看到,聊天室的功能符合要求:


http://www.ppmy.cn/embedded/21425.html

相关文章

数据科学与大数据(学习记录)

这个专业或者方向&#xff0c;这个行业有一句话叫做工具决定下限&#xff0c;分析决定上限。通过数据解决问题的思路是最重要的&#xff0c;对于这类型人才.数据具有四大特性&#xff0c;一个是可以反复使用&#xff0c;一个是客观,量化,机器可处理.常见的分析流程&#xff0c;…

C语言操作符和关键字

文章目录 操作符单目操作符sizeof&#xff08;类型&#xff09;强制类型转换 关系操作符、逻辑操作符、条件操作符逗号表达式 常见关键字typedefstaticstatic修饰局部变量static修饰全局变量static修饰函数 register寄存器关键词define定义常量和宏 操作符 单目操作符 C语言中…

深度解析 Spring 源码:揭秘BeanFactory 之谜

文章目录 一、认识BeanFactory1.1 BeanFactory的概述1.2 BeanFactory与 ApplicationContext的区别 二、BeanFactory源码解读2.1 BeanFactory 接口2.1.1 getBean()2.1.2 containsBean()2.1.3 isSingleton() 2.2 DefaultListableBeanFactory 类2.2.1 registerBeanDefinition()2.2…

基于FPGA的频率计与串口通信(二)

接上篇&#xff0c;本文章展示基于FPGA的频率计与串口通信项目部分核心代码。 顶层文件 top.bdf //#pragma file_not_in_maxplusii_format (header "graphic" (version "1.3")) (pin(input)(rect 80 328 248 344)(text "INPUT" (rect 133 0 1…

c++初阶-----STL---vector

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

企业常用Linux三剑客awk及案例/awk底层剖析/淘宝网cdn缓存对象分级存储策略案例/磁盘知识/awk统计与计算-7055字

高薪思维&#xff1a; 不愿意做的事情:加班&#xff0c;先例自己在利他 生活中先利他人在利自己 感恩&#xff0c;假设别人帮助过你&#xff0c;先帮助别人&#xff0c;感恩境界 awk三剑客老大 find其实也算是一种新的第四剑客 find 查找文件 查找文件&#xff0c;与其他命令…

数据结构--双向链表

在讲双向链表之前&#xff0c;我们先了解一下链表的分类&#xff1a; 链表的结构⾮常多样&#xff0c;主要分为带头与不带头、单向与双向、循环与不循环。三个种类可以任意搭配&#xff0c;所以总共可以形成八种链表&#xff0c;但是最常用的是单向不带头不循环链表和双向带头循…

数字孪生和新质生产力

数字孪生是行业数字化的必经之路在文旅、工业、园区、农业等行业在数字化的发展中&#xff0c;尤其是企业规模较大的工业&#xff0c;物流园区等&#xff0c;面临着越来越多的挑战&#xff0c;如&#xff1a;设备设施老旧、运维成本高昂、能耗过大、安全风险频发等问题&#xf…

周报_2024/4/28

周报 时间 2024/4/22——2024/4/28 科研进展 尝试几种特征筛选方法得出的多种特征子集&#xff0c;默认模型效果提升明显但是问题依然存在&#xff0c;且使用特征筛选后triplet loss效果提升不明显。 重新构造了数据集&#xff0c;保留了流级数据的特征和时序特征。 正在给邵…

Docker 容器操作

容器创建 就是将镜像加载到容器的过程。 新创建的容器默认处于停止状态&#xff0c;不运行任何程序&#xff0c;需要在其中发起一个进程来启动容器。 格式&#xff1a;docker create [选项] 镜像 常用选项&#xff1a; -i&#xff1a;让容器开启标准输入 -t&#xff1a;让…

目标检测YOLO数据集的三种格式及转换

目标检测YOLO数据集的三种格式 在目标检测领域&#xff0c;YOLO&#xff08;You Only Look Once&#xff09;算法是一个流行的选择。为了训练和测试YOLO模型&#xff0c;需要将数据集格式化为YOLO可以识别的格式。以下是三种常见的YOLO数据集格式及其特点和转换方法。 1. YOL…

信息系统项目管理师——第5章信息系统工程(一)

近几期的考情来看&#xff0c;本章选择题稳定考4分&#xff0c;考案例的可能性有&#xff0c;需要重点学习。本章节专业知识点特别多。但是&#xff0c;只考课本原话&#xff0c;大家一定要把本章至少通读一遍&#xff0c;还要多刷题&#xff0c;巩固重点知识。 1 软件工程 软…

20240330-1-词嵌入模型w2v+tf-idf

Word2Vector 1.什么是词嵌入模型&#xff1f; 把词映射为实数域向量的技术也叫词嵌⼊ 2.介绍一下Word2Vec 谷歌2013年提出的Word2Vec是目前最常用的词嵌入模型之一。Word2Vec实际是一种浅层的神经网络模型&#xff0c;它有两种网络结构&#xff0c;分别是连续词袋&#xff…

绿葆自助取袋机公益环保,已为1000多家医院提供派袋便民服务

塑料的广泛应用极大地方便了人们的日常生活&#xff0c;但同时也给地球带来了严重的环境问题——“白色污染”。目前&#xff0c;废弃塑料的回收率仍然很低&#xff0c;高值化利用水平也相对较低。每年我国产生的废弃塑料中&#xff0c;只有极少数能够得到有效回收利用&#xf…

MongoDB磁盘空间占满,导致数据库被锁定,如何清理数据和磁盘空间

一、问题 1、我在实际项目中&#xff0c;遇到一个问题&#xff0c;随着数据每天的不断增加&#xff0c;导致mongodb的磁盘空间站满了&#xff0c;数据库被锁了&#xff0c;无法使用。 2、故障表现 部署的应用程序突然无法将数据写入数据库&#xff0c;但是可以正常读取数据。…

java解析PDF、WORD获取其中的表格以及文本内容

近期因工作需要需要解析PDF&#xff0c;需要把PDF中的文本和表格分离&#xff0c;最终要实现的目标是PDF中的文本内容放一块&#xff0c;表格内容放一块&#xff0c;以list的形式存储。解析PDF的技术有很多&#xff0c;经过多次尝试发现使用AdobeAcrobat可以实现表格和文本分离…

机器学习周报第36周 AT-LSTM

文章目录 week36 AT-LSTM摘要Abstract一、文献阅读1. 题目2. abstract3. 网络架构3.1 LSTM3.2 注意力机制概述3.3 AT-LSTM3.4 数据预处理 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程4.3.1 训练参数4.3.2 数据集4.3.3 实验设置4.3.4 实验结果 5. 基于pytorch的transfor…

关于 nextTick 方法

1、nextTick 方法定义 Vue.js 提供的一个异步方法&#xff0c;用于在下次 DOM 更新循环结束之后执行延迟回调。具体来说&#xff0c;当你想要在当前数据变化之后&#xff0c;DOM 更新之前执行一些操作时&#xff0c;就可以使用 nextTick 方法。 2、nextTick 触发时机 Vue 会在…

Unity打开Android文件管理器并加载文件

1、在AssetStore商店中加入免费插件 2、调用代码 3、使用UnityWebRequest加载路径数据

github two-factor authentication是个啥?

最近在逛github时&#xff0c;总是时不时会弹出一下界面&#xff0c;很烦 看到红框里的文字&#xff0c;这明显是强制要求做这个认证&#xff0c;如果不认证4天后账号将不可访问&#xff0c;所以今天花点时间看看怎么做这个认证&#xff0c;点“Enable 2FA now”进入这个界面&a…