多用户即时通讯系统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. iPhone 15 Pro Max的Type-C接口有多牛?实测USB3比USB2快11倍

    苹果最新的iPhone 15系列和iPhone 15 Pro系列新机,尽管两者都是Type-C接口,但速度相差20倍. 据了解,iPhone 15 Pro/Max搭载的苹果A17 Pro芯片内含专门的 ...

  2. unordered_map模拟实现|STL源码剖析系列|开散列

    博主很久没有更新过STL源码剖析这个系列的文章了,主要是因为大部分STL常用的容器,博主都已经发过文章了,今天博主带着大家把哈希表也模拟实现一下. 前言 那么这里博主先安利一下一些干货满满的专栏啦! ...

  3. PHP常用类

    PHP常用类 一.分页类 <?php /** * 分页类 * 调用方式: * $p=new Page(总条数,显示页码链接数量,当前页码,每页显示条数,[链接]); * print_r($p-& ...

  4. (数据科学学习手札158)基于martin为在线地图快速构建精灵图服务

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,martin作为快速发展中的新 ...

  5. GJK算法:两个凸集的碰撞测试

      GJK算法用于判断两个凸集是否相交,其中GJK是三个提出者的姓名首字母.为了便于理解(偷懒),下面的内容都只在二维平面内讨论. 1. 回顾凸集   可能有很多小伙伴忘了什么是凸集.凸集有很多等价的 ...

  6. HTTP 400 Bad Request 错误。

  7. Linux-yum卸载软件包

    yum是Linux操作系统中最常用的软件包管理器之一,它可以帮助你很容易地安装.删除和更新软件包.然而,有时候yum在删除软件包时可能会出现一些问题,本文将告诉你如何正确地使用yum卸载软件包,并解决 ...

  8. C# 二十年语法变迁之 C# 7参考

    C# 二十年语法变迁之 C# 7参考 https://benbowen.blog/post/two_decades_of_csharp_iii/ 自从 C# 于 2000 年推出以来,该语言的规模已经 ...

  9. Ubuntu下通过Wine安装LTSpice 17.1.8

    LTSpice LTSpice 是常用的电路模拟软件, 但是只有 Windows 版本和 Mac 版本, 在 Linux 下需要用 Wine 运行. 以下说明如何在 Ubuntu 下安装最新的 LTS ...

  10. spring boot和redis实现自定义前后分离token认证

    说明:文章部分代码引用自github 本项目地址:https://gitee.com/indexman/redis-token-demo 1.token认证流程 此处以前端页面请求后端用户列表接口为例 ...