多用户即时通讯系统04

4.编码实现03

4.6功能实现-发送文件功能实现

4.6.1思路分析

客户端(发送者):

  1. 先把文件a.jpg读取到客户端的字节数组
  2. 把文件对应的字节数组封装到message对象[包含文件内容,发送者,接收者]
  3. 将message对象发送到服务端

服务端:

  1. 接收到message对象
  2. 拆解message对象的getteruid,获取接收者用户的通信线程,得到socket
  3. 把message转发给指定用户

客户端(接收者):

  1. 在接收到包含有文件的message消息后,读取对应的文件字节数组,将该数组刷出到磁盘

4.6.2代码实现

1. 客户端:
1.修改MessageType接口

在该接口中拓展消息类型

String MESSAGE_FILE_MES = "8";//表示发送文件消息
2.修改Message类

扩展 和文件相关的成员和方法

//进行扩展 和文件相关的成员
private byte[] fileBytes;
private int fileLen = 0;
private String dest ;//将文件传输到哪里
private String src;//源文件路径 public byte[] getFileBytes() {
return fileBytes;
} public void setFileBytes(byte[] fileBytes) {
this.fileBytes = fileBytes;
} public int getFileLen() {
return fileLen;
} public void setFileLen(int fileLen) {
this.fileLen = fileLen;
} public String getDest() {
return dest;
} public void setDest(String dest) {
this.dest = dest;
} public String getSrc() {
return src;
} public void setSrc(String src) {
this.src = src;
}
3.创建FileClientService

该类完成文件传输服务

package qqclient.service;

import qqcommon.Message;
import qqcommon.MessageType; import java.io.*; /**
* @author 李
* @version 1.0
* 该类完成 文件传输服务
*/
public class FileClientService {
/**
* @param src 源文件
* @param dest 把该文件传输到对方的哪个目录
* @param senderId 发送用户的id
* @param getterId 接收用户的id
*/
public void sendFileToOne(String src, String dest, String senderId, String getterId) {
//读取src文件--封装-->message对象
Message message = new Message();
message.setMesType(MessageType.MESSAGE_FILE_MES);//设置为文件类型
message.setSender(senderId);
message.setGetter(getterId);
message.setSrc(src);
message.setDest(dest); //需要将文件读取到程序中
FileInputStream fileInputStream = null;
byte[] fileBytes = new byte[(int) new File(src).length()];//创建一个和文件大小对应的字节数组 try {
fileInputStream = new FileInputStream(src);
fileInputStream.read(fileBytes);//将src的文件读入到程序的字节数组
//将文件对应的字节数组设置成message对象
message.setFileBytes(fileBytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
//关闭流
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("\n" + senderId + " 给 " + getterId + " 发送文件:" + src +
" 到对方的电脑目录: " + dest); //发送
try {
//从管理线程的集合中,拿到发送者id的线程,
// 在该线程对应的属性socket中得到输出流,将输出流转为对象输出流
ObjectOutputStream oos =
new ObjectOutputStream(ManageClientConnectServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());
oos.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.修改ClientConnectServerThread类

在在该类中增加接收message消息的类型,并进行相应的操作

else if (message.getMesType().equals(MessageType.MESSAGE_FILE_MES)) {
//接收到的是文件类型的消息
//把服务器转发的message对象
System.out.println("\n" + message.getSender() + " 给 " + message.getGetter() +
" 发送文件: " + message.getSrc() + " 到我的电脑的目录:" + message.getDest());
//取出message文件的字节数组,通过文件输出流写出到磁盘
FileOutputStream fileOutputStream =
new FileOutputStream(message.getDest());
fileOutputStream.write(message.getFileBytes());
fileOutputStream.close();
System.out.println("\n保存文件成功~");
}

5.修改QQView

1.在该类中创建FileClientService对象

private FileClientService fileClientService = new FileClientService();//该对象用于文件传输

在该类中通过键盘,将用户输入传送到sendFileToOne方法中

case "4":
System.out.println("请输入你希望发送文件的用户(在线):");
getterId = Utility.readString(50);
System.out.println("请输入要发送文件的路径:(形式如:d:\\xx.jpg)");
String src = Utility.readString(100);
System.out.println("请输入把文件发送到对方电脑下的路径:(形式如:d:\\yy.jpg)");
String dest = Utility.readString(100);
fileClientService.sendFileToOne(src,dest,userId,getterId);
break;
2.服务端
1.修改MessageType接口

在该接口中拓展消息类型

 String MESSAGE_FILE_MES = "8";//表示发送文件消息
2.修改Message类

扩展 和文件相关的成员和方法

//进行扩展 和文件相关的成员
private byte[] fileBytes;
private int fileLen = 0;
private String dest ;//将文件传输到哪里
private String src;//源文件路径 public byte[] getFileBytes() {
return fileBytes;
} public void setFileBytes(byte[] fileBytes) {
this.fileBytes = fileBytes;
} public int getFileLen() {
return fileLen;
} public void setFileLen(int fileLen) {
this.fileLen = fileLen;
} public String getDest() {
return dest;
} public void setDest(String dest) {
this.dest = dest;
} public String getSrc() {
return src;
} public void setSrc(String src) {
this.src = src;
}
3.修改ServerConnectClientThread类

在该类的run方法中增加服务端接收文件并转发的业务

else if (message.getMesType().equals(MessageType.MESSAGE_FILE_MES)) {
//业务五:客户请求给某用户发送文件
//根据接收的message对象的getter id 获取到对应的线程,将message对象进行转发
//拿到线程
ServerConnectClientThread serverConnectClientThread =
ManageClientThreads.getServerConnectClientThread(message.getGetter());
//获取socket,将socket输出流转为对象流
ObjectOutputStream oos =
new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
//转发
oos.writeObject(message);
}

运行:

1.运行服务端

2.运行客户端,登录两个用户(100,200)

3.用户100 尝试给用户200 发送文件

用户100:

用户200:

用户200的磁盘下成功接收到文件:

4.服务端

功能实现完毕

day04-2发送文件的更多相关文章

  1. win7系统下的飞秋发送文件失败问题

    飞秋发送文件失败这个问题大多数是由防火墙引起的1.检查windows自带的防火墙设置,在左侧的"允许程序通过windows防火墙"查看飞秋是否存在,不存在则增加之,公网.专网都勾选 ...

  2. 利用Socket远程发送文件

    思想: 1.注意使用两个通道,一个普通对象通信通道,另一个纯净的文件字节流通道 2.利用通信通道发送文件请求,新建字节流通道,开始发送文件

  3. [转]C#网络编程(订立协议和发送文件) - Part.4

    本文转自:http://www.tracefact.net/CSharp-Programming/Network-Programming-Part4.aspx 源码下载:http://www.trac ...

  4. android开发,socket发送文件,read阻塞,得不到文件尾-1

    这是我的接收文件代码:开始可以读取到-1,但是现在又读取不到了,所以才加上红色字解决的(注释的代码) File file = new File(mfilePath,"chetou." ...

  5. tengine lua 开源一 调用内部接口高效发送文件

    tengine  lua 开源一 调用内部接口高效发送文件 开源自己封装的sendfile 模块,可以高效的通过lua发送文件 源码地址:https://github.com/weinyzhou/Lu ...

  6. ASP.NET MVC:通过 FileResult 向 浏览器 发送文件

    在 Controller 中我们可以使用 FileResult 向客户端发送文件. FileResult FileResult 是一个抽象类,继承自 ActionResult.在 System.Web ...

  7. socket(TCP)发送文件

    一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.Componen ...

  8. xmpp发送文件

    xmpp 文件传输协议: XEP-0096: SI File Transfer:文件传输流初始化协议 XEP-0065: SOCKS5 Bytestreams:带外socks5代理字节流传输协议 XE ...

  9. C#_Socket网络编程实现的简单局域网内即时聊天,发送文件,抖动窗口。

    最近接触了C#Socket网络编程,试着做了试试(*^__^*) 实现多个客户端和服务端互相发送消息 发送文件抖动窗口功能 服务端: using System; using System.Collec ...

  10. Smack+Openfire 接收和发送文件

    转载请注明出处:http://blog.csdn.net/steelychen/article/details/37958839 发送文件须要提供准确的接收放username称(例:user2@192 ...

随机推荐

  1. ChatGPT - 圈里的百科

    ChatGPT(全名:Chat Generative Pre-trained Transformer),美国OpenAI [1]  研发的聊天机器人程序 [12]  ,于2022年11月30日发布 [ ...

  2. 你天天用4G 这些基本常识都知道吗?

    不少朋友在选购4G智能手机的时候,经常可能会遇到这样的名词,五模十三频.五模十七频.双4G.移动4G.联通4G.那这些名词到底是什么意思呢?它们之间又有什么区别呢? 其实上面的这些说法其实都是比较具有 ...

  3. Azure Data Factory(十二)传参调用 Azure Function

    一,引言 在实际的项目中,Azure Data Factroy 中的 Data Flow 并不能彻底帮我们完成一系列复制逻辑计算, 比如我们需要针对数据集的每一行数据进行判断计算,Data Flow ...

  4. 解决每次 git pull/push 时都需要输入账号和密码的问题

    问题 在提交代码或者拉取代码的时候,如果每次git都要输入用户名密码 解决方法 1. 终端输入 git config --global credential.helper store 2. 在git ...

  5. Python实现二叉查找

    搜索 搜索是在一个项目集合中找到一个特定项目的算法过程.搜索通常的答案是真的或假的,因为该项目是否存在. 搜索的几种常见方法:顺序查找.二分法查找.二叉树查找.哈希查找 二分法查找 二分查找又称折半查 ...

  6. NC15033 小G有一个大树

    题目链接 题目 题目描述 小G想要把自己家院子里的橘子树搬到家门口(QAQ..就当小G是大力水手吧) 可是小G是个平衡性灰常灰常差的人,他想找到一个这个橘子树的平衡点. 怎么描述这棵树呢...就把它看 ...

  7. STC89C52驱动MAX7219LED点阵级联, 文字滚动效果

    级联下的传值方式 级联下, N个MAX7219相当于组成了一个8*N bit宽度的锁存器, 如果需要对第M个7219进行写入, 需要做M次寻址+写入后拉高CS, 才能到达这个7219. 如果仅仅对这个 ...

  8. CentOS8-pacemaker+corosync高可用部署

    部署pacemaker yum install pacemaker pcs corosync fence-agents resource-agents 启动pcs服务 systemctl enable ...

  9. java.lang.System快速指南

    1.介绍 在本教程中,我们将快速了解java.lang.System类及其特性和核心功能. 2.IO 系统类是java.lang的一部分,它的一个主要特性是让我们能够访问标准的I/O流. 简单地说,它 ...

  10. 如何设置 vcpkg 依赖特定编译器

    最近项目要部署到 gitlab-ci 上,所以远程机器上也要安装好编译环境 在相关的环境安装完后,发现编译项目时提示找不到三方库的符号文件 看到这个错误的第一反应就是依赖库的版本不对,因为远程机器上不 ...