网络通讯聊天工具的实现v2

在原有基础上加入文件的传输功能。

从客户端传送到服务器后,服务器接受文件,再转发给其他客户端,客户端接受后服务器删除文件。

涉及文件的读取与关闭。

1.原来传输的改进

1.1服务器需要区分传输的是文件还是信息。

        在传输之前先传输一个0/1让其判断是否为文件,其中0表示文件。

2.客服端clint:

        在里面添加了一个传输文件的方法outputFIle();

File类只存储文件的相关信息,如文件路径等等。因此文件的传输需要将文件的内容发送过去。

使用fileinputstream来读取文件的信息,DataOutputStream其有一些便捷的方式将数据转化为字节流,用他来传输文件内容。

现将文件的名字,以及群聊或者私聊及其对象传送过去,接着写入文件。定义一个1024大小的字节数组。使用read方法进行读取,此方法返回读取的长度。当读完文件后返回-1。读取1024字节大小后使用dos.write()写入。最后需要关闭文件的读取流,释放资源。

public void outputFile(File file,int index){try {//让其判断是文件还是信息os.write(0);//表示文件fis = new FileInputStream(file);dos = new DataOutputStream(os);//文件名,大小等属性dos.writeUTF(file.getName());dos.flush();//确保数据立即发送//发送群聊或者私聊String s;if (IMG[1] == 0) {s = IMG[1]+"";} else {s = PORT.get(index);}dos.writeUTF(s);dos.flush();dos.writeLong(file.length());dos.flush();//传输文件System.out.println("传输文件");byte[] bytes = new byte[1024];int length ;//读取文件file,并传输while((length = fis.read(bytes,0, bytes.length)) != -1){//每次读取1024个字节dos.write(bytes,0,length);dos.flush();}//释放文件读取流fis.close();System.out.println("发送成功");} catch (IOException e) {throw new RuntimeException(e);}}

2.2按钮监听

在按钮中增添了发送文件的按钮。

并创建一个文件选择器的对象,选择文件后记录在file中,并调用上诉发送文件的方法。

else if (ae.equals("发送文件")) {System.out.println("发送文件");JFileChooser jfc = new JFileChooser();int result = jfc.showOpenDialog(null);if (result == JFileChooser.APPROVE_OPTION) {File file = jfc.getSelectedFile();//发送给服务器int index = groupOrPrivate();clint.outputFile(file, index);}}

2.3服务端的接受线程:

与发送类似先判断是消息还是文件,调用对应方法。

@Overridepublic void run() {while (true) {try {int type = is.read();if (type == 1) {//消息getMsg();} else if (type == 0) {//文件saveFile();}} catch (IOException e) {throw new RuntimeException(e);}}}

存储文件方法saveFile();

与写入类似,只不过使用datainputstream进行读取,fileoutputstream进行写入。

接受到文件名后存入fileName中 与大小后 创建相应文件名对象。同读取文件方法类似的写入方法。不过需要判断已经接受字节的大小,来停止文件的接受。因为接受文件的传输没有读取返回的-1。也可以使用接受到特定的字节时停止。最后关闭文件输出流。

public void saveFile() {try {System.out.println("接受文件");dis = new DataInputStream(is);String fileName = dis.readUTF();long fileLength = dis.readLong();File file = new File("C:\\Users\\15697\\IdeaProjects\\Pro24\\src\\ChatV3\\Client\\GetFile" + File.separatorChar + fileName);fos = new FileOutputStream(file);System.out.println("检测到文件名为:" + fileName + "开始接受文件");byte[] bytes = new byte[1024];int length;long readLength = 0;while ((length = dis.read(bytes, 0, bytes.length)) != -1) {fos.write(bytes, 0, length);fos.flush();readLength +=length;if(readLength >= fileLength){break;}}//关闭文件输出流fos.close();System.out.println("文件接受完毕");sendMsg("-----接受到文件:"+fileName+"请查看------");} catch (IOException e) {throw new RuntimeException(e);}}

服务端:

发送给客户端数据同样再加上消息还是文件的判定。

同时接受信息与客户端接受信息一致,需要接受文件。接受后还需要发送给指定用户。

 @Overridepublic void run() {while (true) {getIMG();}}//接受消息public void getIMG() {try {int type = is.read();//判断文件 还是信息if (type == 1) {System.out.println("接受消息");getMessage();} else if (type == 0) {System.out.println("为文件");//接受文件getFile();}} catch (IOException e) {throw new RuntimeException(e);}}

getFile();先进行文件的获取,接着判断接受的对象名s为0则是群聊,其他的则是其他客户端的端口号。为群聊则调用

groupOutputFile(file);

私聊则调用先确定私聊的对象接着调用

outputFile(file);

即可。

public void getFile() {try {dis = new DataInputStream(is);String fileName = dis.readUTF();String s = dis.readUTF();//私发用户System.out.println("对象:" + s);long fileLength = dis.readLong();File file = new File("C:\\Users\\15697\\IdeaProjects\\Pro24\\src\\ChatV3\\Server\\temFile" + File.separatorChar + fileName);fos = new FileOutputStream(file);System.out.println("检测到文件名为:" + fileName + "开始接受文件");byte[] bytes = new byte[1024];int length;long readLength = 0;while ((length = dis.read(bytes, 0, bytes.length)) != -1) {//客户端读取-1时以及停止所以未发送过来,因此会陷入while中等待读取,需要我们加入一个-1fos.write(bytes, 0, length);fos.flush();readLength += length;if(readLength >= fileLength){break;}}System.out.println("文件接受完毕");//接受发送对象//dis.close();if (s.equals("0")) {//群聊System.out.println("群发文件");//文件群聊发送groupOutputFile(file);} else {//私发int size = sockets.size();for (int i = 0; i < size; i++) {System.out.println("查找私发文件对象");Socket temSocket = sockets.poll();if (s.equals(String.valueOf(temSocket.getPort()))) {//给私聊对象发送//发送信号给客户端是否接受文件os = temSocket.getOutputStream();outputFile(file);//删除文件deleteFile(file);}sockets.offer(temSocket);}//发送给消息对象os = socket.getOutputStream();output("文件发送成功");}} catch (IOException e) {throw new RuntimeException(e);} }
public synchronized void groupOutputFile(File file) {try {int size = sockets.size();for (int i = 0; i < size; i++) {System.out.println("多少个用户端:" + sockets.size());Socket temSocket = sockets.poll();os = temSocket.getOutputStream();outputFile(file);sockets.offer(temSocket);}//删除文件deleteFile(file);} catch (IOException e) {throw new RuntimeException(e);}}
public void outputFile(File file) {try {//让其判断是文件还是信息os.write(0);//表示文件fis = new FileInputStream(file);dos = new DataOutputStream(os);//文件名,大小等属性dos.writeUTF(file.getName());dos.flush();//确保数据立即发送dos.writeLong(file.length());dos.flush();//传输文件System.out.println("传输文件");byte[] bytes = new byte[1024];int length;//读取文件file,并传输while ((length = fis.read(bytes, 0, bytes.length)) != -1) {//每次读取1024个字节dos.write(bytes, 0, length);dos.flush();}System.out.println("发送成功");fis.close();fos.close();} catch (IOException e) {throw new RuntimeException(e);} }
public void deleteFile(File file){//删除文件if(file.exists()){boolean isdelete = file.delete();if(isdelete){System.out.println("文件已接受,删除文件成功");}else {System.out.println("文件正在被使用,删除失败");}}}

即可完成文件的传输。

注:文件的的写入与读取后将相应流关闭。关闭后服务器才能删除缓存文件。

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

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

相关文章

Linux基础指令用户管理002

继Linux基础指令用户管理001我们讲述了创建用户和删除用户&#xff0c;我们讲一下如何设置用户密码以及修改用户信息。 操作系统 CentOS Stream 9 设置用户密码 我们使用passwd指令passwd name [rootlocalhost ~]# passwd wg 更改用户 wg 的密码 。 新的密码&#xff1a; …

装机必备——截图软件PixPin安装教程

装机必备——截图软件PixPin安装教程 软件下载 软件名称&#xff1a;PixPin 1.5 软件语言&#xff1a;简体中文 软件大小&#xff1a;30.1M 系统要求&#xff1a;Windows7或更高&#xff0c; 64位操作系统 硬件要求&#xff1a;CPU2GHz &#xff0c;RAM2G或更高 下载通道①迅…

通过LLM多轮对话生成单元测试用例

通过LLM多轮对话生成单元测试用例 代码 在采用 随机生成pytorch算子测试序列且保证算子参数合法 这种方法之前,曾通过本文的方法生成算子组合测试用例。目前所测LLM生成的代码均会出现BUG,且多次交互后仍不能解决.也许随着LLM的更新,这个问题会得到解决.记录备用。 代码 impo…

Inno Setup 深入浅出-文件的显示

【1】在需要打包的文件中&#xff0c;新建一个文本文件&#xff0c;如License.txt 注意&#xff1a;中文的编码格式需要GB2312&#xff0c;否则显示乱码 【2】读取、显示文本 [Code] procedure Init_ShowLicense(); var tmpFont:TFont; begin editLicense : TMemo.C…

OpenFHE 源码解析:BinFHE 部分

参考文献&#xff1a; [ABB22] Al Badawi A, Bates J, Bergamaschi F, et al. Openfhe: Open-source fully homomorphic encryption library[C]//Proceedings of the 10th Workshop on Encrypted Computing & Applied Homomorphic Cryptography. 2022: 53-63.openfheorg/o…

算法训练营day43

题目1&#xff1a;343. 整数拆分 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int integerBreak(int n) {vector<int> dp(n 1, 0);dp[2] 1;for(int i 3;i < n;i) {for(int j 1;j < i;j ) {// j * (i - j)相当于拆分成两个数// j * dp[i …

搭建YOLOv10环境 训练+推理+模型评估

文章目录 前言一、环境搭建必要环境1. 创建yolov10虚拟环境2. 下载pytorch (pytorch版本>1.8)3. 下载YOLOv10源码4. 安装所需要的依赖包 二、推理测试1. 将如下代码复制到ultralytics文件夹同级目录下并运行 即可得到推理结果2. 关键参数 三、训练及评估1. 数据结构介绍2. 配…

kotlin基础之泛型和委托

Kotlin泛型的概念及使用 泛型概念 在Kotlin中&#xff0c;泛型&#xff08;Generics&#xff09;是一种允许在类、接口和方法中使用类型参数的技术。这些类型参数在实例化类、实现接口或调用方法时会被具体的类型所替代。泛型的主要目的是提高代码的复用性、类型安全性和可读…

oracle翻页查询的小坑记录

oracle的查询&#xff0c;因为能获取到查询结果的rownum&#xff0c;就想着直接在查询条件后面做翻页&#xff0c;而且首页确实是正常查询到了。后面才发现翻页是空的。。。 这是因为rownum排序是在查询结果才分配的。所以应该把查询结果作为子查询&#xff0c;在外查询应用排序…

【深度好文】AI企业融合联盟营销,做的好就是最大赢家!

AI工具市场正在迅速发展&#xff0c;现仍有不少企业陆续涌出&#xff0c;那么如何让你的工具受到目标群体的关注呢&#xff1f;这相比是AI工具营销人员一直在思考的问题。 即使这个市场正蓬勃发展&#xff0c;也无法保证营销就能轻易成功。AI工具虽然被越来越多人认可和接受&a…

Windows配置java环境JDK

配置jdk环境非常简单&#xff0c;大概有以下几步&#xff1a; 下载jdk安装&#xff0c;然后双击进行安装配置环境变量(也不是一定非要配置环境变量&#xff0c;配置环境变量的好处就是&#xff0c;在任何位置&#xff0c;系统都可以找到安装路径&#xff0c;非常实用且方便) …

短信平台-平台群发短信

时代的进步带来了我们生活的便利&#xff0c;而其中最受欢迎和广泛应用的方式之一就是通过短信传递信息。在这个飞速发展的数字时代&#xff0c;我们需要一个高效、可靠的短信平台来满足不断增长的通讯需求。而今天&#xff0c;我要向大家推荐的正是这样一款卓越的短信平台——…

连接远程的kafka【linux】

# 连接远程的kafka【linux】 前言版权推荐连接远程的kafka【linux】一、开放防火墙端口二、本地测试是否能访问端口三、远程kafka配置四、开启远程kakfa五、本地测试能否连接远程六、SpringBoot测试连接 遇到的问题最后 前言 2024-5-14 18:45:48 以下内容源自《【linux】》 仅…

封装和解构是 Python 中常用的技术

目录 前言 一、封装&#xff08;Packing&#xff09;&#xff1a; 二、解构&#xff08;Unpacking&#xff09;&#xff1a; 2.1 解构元组或列表&#xff1a; 2.2 解构字典&#xff1a; 2.3 使用*进行解构&#xff1a; 2.4 解构函数返回值 总结 前言 提示&#xff1a;这…

Oracle体系结构初探:RMAN基本配置参数

目录 查看RMAN基本配置 修改RMAN配置参数 基本配置参数说明 查看RMAN基本配置 进入RMAN命令行 rman target / -- “/” 就代表了sysdba权限 查看参数命令 show all; RMAN> show all; RMAN configuration parameters for database with db_unique_name ORCL are:…

leetcode-189. 旋转数组 原地递归算法(非官方的三种方法)

Problem: 189. 轮转数组 思路 首先&#xff0c;很明显&#xff0c;题目要求的操作等同于将数组的后k%n个元素移动到前面来。 然后我们思考原地操作的方法&#xff1a; &#xff08;为了方便讲解&#xff0c;我们先假设k<n/2&#xff09; 1.我们将数组划分为 [A&#xff0c;B…

7. CSS 网格布局

CSS3引入了强大的网格布局&#xff08;Grid Layout&#xff09;&#xff0c;它提供了一种二维的布局方式&#xff0c;使得创建复杂的网页布局变得更加简单和直观。通过定义行和列&#xff0c;我们可以精确控制网页元素的排列和对齐。本章将详细介绍网格布局的基本概念和属性&am…

pytorch学习day1

一.pytorch主要模块介绍 1.1 模块介绍 模块描述torch包含激活函数和主要的张量操作torch.Tensor定义了张量的数据类型&#xff0c;方法可返回新张量&#xff0c;方法后缀带下划线可修改张量本身torch.cuda定义了 CUDA 运算相关的函数&#xff0c;如检查 CUDA 是否可用&#x…

橙派探险记:开箱香橙派 AIpro 与 疲劳驾驶检测的奇幻之旅

橙派探险记&#xff1a;开箱香橙派 AIpro 与 疲劳驾驶检测的奇幻之旅 引子&#xff1a;神秘包裹的到来 在很久很久以前......在一个阳光明媚的下午&#xff0c;我终于收到了期待已久的包裹——香橙派 AIpro。这份礼物辗转两次才到我的手上&#xff0c;每一天我都怀着满心的期待…

JetLinks物联网平台在windows 7搭建(前后端)部署教程

近期对接TCP、modbusTCP等自定义解析&#xff0c;做了很多万能解析的方法&#xff0c;却都不遂人意&#xff0c;而一直在用的ThingsBoard不能直接对接TCP透传(企业版除外)&#xff0c;需要在外围做一些自定义解析&#xff0c;然后转json再mqtt上传&#xff0c;感觉来说比较麻烦…