在局域网中,客户可以将文件分享到网络上,由服务器进行转发给其他客户,其他客户可以接收服务器发来的文件,并保存到本地磁盘中。

以下是大致的工作流程

客户端有三个线程

主线程  1.负责启动 文件发送的线程        2.负责启动文件接收线程

内容如图:

服务端有两个线程,主线程专门接收用的连接,并为每一个连接上服务器的客户创建一个子线程。子线程专门用来接收客户发来的文件,保存本地磁盘,并转发给其他客户。如下:

客户端主线程代码:

import java.net.Socket;//客户端
public class Client {public static void main(String[] args) {try {System.out.println("=======客户端=======");//1.线连接上服务器的套接字 (套接字=ip:端口号)Socket socket = new Socket("127.0.0.1", 10001);//2. 开启一个线程对象 专们用来接收文件的线程new ClientGetFile(socket).start();//3.开启发送文件的线程对象new  ClientSendFile(socket).start();while (true);} catch (Exception e) {e.printStackTrace();}}
}

客户端接收文件子线程代码:

import java.io.*;
import java.net.Socket;
//作为客户端接收文件的线程
public class ClientGetFile extends Thread{private final Socket socket;public ClientGetFile(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {//1.定义 输入流 从网络介质中获取数据存入内存中DataInputStream dis=new DataInputStream(socket.getInputStream());//2. 定义流将文件数据从内存中写入磁盘String FileName = dis.readUTF();String FilePath ="E:\\Documets\\Desktop\\客户\\"+ FileName;System.out.println("正在保存:"+FileName);DataOutputStream outputToDisk = new DataOutputStream(new FileOutputStream(FilePath));byte[] buffer=new byte[8192];long FileLength = dis.readLong();int length;int OKLength=0;while ((length=dis.read(buffer))!=-1){OKLength += length;outputToDisk.write(buffer,0,  length);outputToDisk.flush();if (FileLength==OKLength)break;}System.out.println("接收"+FileName+"成功!");System.out.println("路径为:"+FilePath);outputToDisk.close();       //关闭 内存->磁盘 的io资源} catch (Exception e) {System.out.println("您已离线!!!");e.printStackTrace();}}
}

客户端发送文件子线程代码:

import java.io.*;
import java.net.Socket;
//作为客户端发送文件的线程类
public class ClientSendFile extends Thread{private final Socket socket;public ClientSendFile(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {//1.创建要发送的文件对象File file=new File("E:\\Documets\\Desktop\\老婆.mp4");//2.通过套接字传文件给服务器,由服务器转发给别的客户sendFileToServer(socket,file);System.out.println(file.getName()+"发送完毕!!!");//while (true);} catch (Exception e) {System.out.println("您已离线!!");e.printStackTrace();}}//定义一个静态方法 作为专门发送文件private static void sendFileToServer(Socket socket,File file) throws Exception {//1.将文件对象输入到内存中来DataInputStream InputToRAM=new DataInputStream( new FileInputStream(file) );//2.准备发送管道 发送到网络 给服务器接收DataOutputStream outputToNet= new DataOutputStream( socket.getOutputStream() );//3.发送文件名、文件大小 给服务器outputToNet.writeUTF(file.getName());   //发送文件名给 服务器   file.getName(); 得到要发送的文件名outputToNet.flush();                    //刷新流outputToNet.writeLong(file.length());  // 发送文件大小给 服务器   file.length();得到要发送的文件大小 单位字节(1K=1024Byte)outputToNet.flush();// 4.发送文件内容 给服务器int length;byte[] buffer = new byte[1024];while ((length = InputToRAM.read(buffer)) != -1) {  //dis.read(buffer)  从磁盘中读取内容,存到buffer数组中(数组在内存中)outputToNet.write(buffer,0,length);outputToNet.flush();}}
}

=========================================================================

服务器主线程代码:

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;//使用两个线程 主线程 用于将连接过来的套接字 添加到集合 代表当前在线的人数
public class Server {/*创建一个Socket的list集合 用来装套接字  Socket=(IP地址:端口号)   */public static final List<Socket> onLineSockets = new ArrayList<>();  //当客户端连接上服务器的时候,就将客户端的套接字存入集合中public static void main(String[] args) {try {System.out.println("===服务端启动成功===");// 1、注册端口ServerSocket serverSocket = new ServerSocket(10001);// a.定义一个死循环由主线程负责不断的接收客户端的Socket管道连接。while (true) {// 2、每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取消息Socket socket = serverSocket.accept();System.out.println(socket.getRemoteSocketAddress()+ "上线了!");onLineSockets.add(socket);// 把当前客户端管道Socket加入到在线集合中去// 3、开始创建独立线程处理这个连接上来的客户new ServerFileThread(socket).start();}} catch (Exception e) {System.out.println("您已离线!");e.printStackTrace();}}
}

服务器子线程,负责文件的保存和转发:

import java.io.*;
import java.net.Socket;
//服务端转发文件给客户线程
public class ServerFileThread extends Thread{private final Socket socket;                      //用来存套接字public ServerFileThread(Socket socket){   //构造方法,用来接收  与服务器连接的管道对管道进行读操作this.socket = socket;}@Overridepublic void run() {try {//1.得到客户的通信管道DataInputStream InputToRAM=new DataInputStream(socket.getInputStream());//2.准备输出流  一个输出到服务器的本地磁盘下,一个输出到网络介质上,让其他客户接收DataOutputStream outputToDisk;DataOutputStream outputToNet = new DataOutputStream(socket.getOutputStream());//3. 接收和转发文件    (接收是接收到服务器的磁盘下,转发是转发到 网络介质上给别的客户)while (true) {// 获取文件名字和文件长度String FileName = InputToRAM.readUTF();String FilePaht ="E:\\Documets\\Desktop\\服务器\\"+ FileName;System.out.println("正在接收:"+FileName);outputToDisk=new DataOutputStream(new FileOutputStream(FilePaht));long FileLength = InputToRAM.readLong();// 发送文件名字和文件长度给所有客户端for(Socket onLineSocket : Server.onLineSockets) { //onLineSockets存的是当前连接的客户if(onLineSocket!= socket) {       // 发送给其它客户端outputToNet.writeUTF(FileName);outputToNet.flush();outputToNet.writeLong(FileLength);outputToNet.flush();}}//真正传送文件数据int length;long OKLength = 0;byte[] buffer = new byte[8192];while ((length = InputToRAM.read(buffer)) != -1) {OKLength += length;        //记录已经传输的文件大小//存到服务器的磁盘下outputToDisk.write(buffer, 0, length);outputToDisk.flush();//转发数据到每个用户for(Socket onLineSocket : Server.onLineSockets) {if(onLineSocket != socket) {  // 发送给其它客户端,outputToNet.write(buffer, 0, length);outputToNet.flush();}}if(OKLength == FileLength) {  // 强制退出break;}}System.out.println(FileName+"转发完毕!");System.out.println(FileName+"保存到服务器的路径为:"+FilePaht);outputToDisk.close();           //关闭 内存->磁盘 的io资源}} catch (IOException e) {Server.onLineSockets.remove(socket);System.out.println(socket.getRemoteSocketAddress()+"已下线~");     //该用户已经断开连接System.out.println("当前在线人数:"+Server.onLineSockets.size());// e.printStackTrace();}}
}

实验结果:

服务器

客户端:

在E:\Documets\Desktop\服务器\下有 “老婆.mp4” 文件,且可以正常打开

在E:\Documets\Desktop\客户\路径下也有,并可以正常打开

再来说说怎么解决 服务器怎么区别,客户发来的文件 是什么类型的文件,解决的办法是先将问文件名和文件大小发送给服务器,然后让服务器分配好io输出到本地磁盘的路径,之后再进行文件数据的传输,这样就可以了,详情参考上面的代码。

Java模拟文件发送给服务器,服务器将文件转发给其他用户,并保存到服务器本地,其他用户可以接收,并保存到本地磁盘,支持各种文件格式,并解决通信中服务器怎么区分客户端发来的文件类型相关推荐

  1. TCP通信中服务器处理客户端意外断开

    如果TCP连接被对方正常关闭,也就是说,对方是正确地调用了closesocket(s)或者shutdown(s)的话,那么上面的Recv或Send调用就能马上返回,并且报错.这是由于close soc ...

  2. Tcp通信中服务器处理客户端意外断开!

    所谓意外断开,是客户端(多指支持3G的移动设备)并没有正常关闭socket,双方并未按照协议上的四次挥手去断开连接,一般的处理办法都是利用保活机制.而保活机制分又可以让底层实现也可自己实现. 一.双方 ...

  3. [已解决]Keil 中出现No Browse Information available in ‘工程文件‘的

    在查看程序时想要Go to Definition of  'xxx' 但是会出现如图所示的提醒: 解决方法: 点击魔术棒,再在Output的选项中勾选Browse Information,如此就可以正 ...

  4. gvim支持python3编译,解决omnicppcomplete中python3complete报错:requried vim complied with +python3

    软件版本: gvim82,python3.6,mingw-w64(gcc 8.1) 问题描述: 1.在_vimrc文件中添加: autocmd Filetype python set omnifunc ...

  5. 微服务接入oauth2_SpringCloud微服务实战系列(十九)Ouath2在真实场景中的应用之客户端接入(第一种写法)...

    SpringCloud微服务实战系列(十九)Ouath2在真实场景中的应用之客户端接入(第一种写法) 一.概述 在<SpringCloud微服务实战系列(十七)Ouath2在真实场景中的应用之资 ...

  6. 如何在Webstorm/Phpstorm中设置连接FTP,并快速进行文件比较,上传下载,同步等操作...

    Phpstorm除了能直接打开localhost文件之外,还可以连接FTP,除了完成正常的数据传递任务之外,还可以进行本地文件与服务端文件 的异同比较,同一文件自动匹配目录上传,下载,这些功能是平常I ...

  7. java.sql.SQLException: 不支持的字符集 (在类路径中添加 orai18n.jar): ZHS16GBK

    今天在搭建一个SpringBootJPA的项目中,启动遇到以下报错 java.sql.SQLException: 不支持的字符集 (在类路径中添加 orai18n.jar): ZHS16GBK 在po ...

  8. 该微信用户未开启“公众号安全助手”的消息接收功能,请先开启后再绑定,Java微信公众号开发消息推送公众号用户绑定问题 的解决办法

    问题概述 在进行微信公众号开发的时候遇到的这个问题,通过Web开发公众号的模板消息推送,在调试的过程中,需要进行开发者接口联调&调试,在调试之前需要将当前的公众号与用户的微信号进行绑定, 绑定 ...

  9. js读取服务器txt文件,ZK中使用JS读取客户端txt文件内容问题

    最近写一个需求时遇到一个问题,用户需要通过点击一个按钮直接读取他自己电脑上D盘的一个txt文件内容显示到页面,因为项目现在是用ZK写的.我对于ZK也是刚刚了解不就,很多都还不是很熟.起初我是想用io流 ...

最新文章

  1. 设计模式笔记(9)---组合模式(结构型)
  2. 事务隔离性与隔离级别
  3. 尽快安装修补程序!微软 Word 漏洞影响上百万人
  4. 只须9招牵着职场幸福走
  5. linux的as编译文件,Ubuntu Linux14 64位下在Android studio下用gradle编译Andrid项
  6. Linux shell编程:状态变量
  7. img标签设置display:block,宽度无法100%
  8. 朴素贝叶斯与贝叶斯网络
  9. Java 8 API Stream让List操作更便捷
  10. docker 实战---使用oracle xe作为开发数据库(六)
  11. prism v2之旅(7)
  12. 自学python顺序-Python学习之调换顺序
  13. python做数据排序,python 实现对数据的排序和绘图
  14. 浅谈Spring如何利用三个缓存Map解决循环依赖
  15. Si9000阻抗计算笔记(一)
  16. Jmeter接口测试及接口性能测试
  17. matlab机器人运动仿真,基于MATLAB机器人手臂运动仿真
  18. 六大CPU体系结构:X86、 ARM、MIPS、PowerPC、Sparc、Alfa发展
  19. 后台管理系统之用JQuery-validate做表单验证
  20. 解决TOC与目录导航冲突问题

热门文章

  1. 单项式计算机在线使用,16进制(CRC16)(多项式异或,多种)校验(2),循环冗余校验在线计算器_三贝计算网_23bei.com...
  2. c语言float、double数据保留2位小数
  3. 国内著名杀毒软件厂商江民公司的主页遭到黑客攻击
  4. 新天地-----周华健新歌
  5. 汽车UDS诊断之安全访问服务(0x27)深度剖析
  6. ajax没返回响应数据,jQuery的Ajax时无响应数据的解决方法
  7. Windows Phone 7 开发 31 日谈——第12日:使手机震动
  8. 从思维角度去探讨epoll机制
  9. 用数组处理整型变量c语言,C语言回顾-整型变量修饰符和一维数组
  10. java 获取两条经纬度线段的交点坐标工具类