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

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

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

以下是大致的工作流程

客户端有三个线程

主线程  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;
    }
    @Override
    public 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;
    }
    @Override
    public 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;
    }
    @Override
    public 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输出到本地磁盘的路径,之后再进行文件数据的传输,这样就可以了,详情参考上面的代码。

相关文章
|
2月前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
100 9
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
107 2
|
19天前
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
88 9
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
25天前
|
人工智能 JSON Linux
利用阿里云GPU加速服务器实现pdf转换为markdown格式
随着AI模型的发展,GPU需求日益增长,尤其是个人学习和研究。直接购置硬件成本高且更新快,建议选择阿里云等提供的GPU加速型服务器。
利用阿里云GPU加速服务器实现pdf转换为markdown格式
|
1月前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
102 34
|
2月前
|
JSON Java 程序员
Java|如何用一个统一结构接收成员名称不固定的数据
本文介绍了一种 Java 中如何用一个统一结构接收成员名称不固定的数据的方法。
39 3
|
2月前
|
消息中间件 存储 Java
RocketMQ文件刷盘机制深度解析与Java模拟实现
【11月更文挑战第22天】在现代分布式系统中,消息队列(Message Queue, MQ)作为一种重要的中间件,扮演着连接不同服务、实现异步通信和消息解耦的关键角色。Apache RocketMQ作为一款高性能的分布式消息中间件,广泛应用于实时数据流处理、日志流处理等场景。为了保证消息的可靠性,RocketMQ引入了一种称为“刷盘”的机制,将消息从内存写入到磁盘中,确保消息持久化。本文将从底层原理、业务场景、概念、功能点等方面深入解析RocketMQ的文件刷盘机制,并使用Java模拟实现类似的功能。
53 3
|
2月前
|
Java 测试技术 Maven
Maven clean 提示文件 java.io.IOException
在使用Maven进行项目打包时,遇到了`Failed to delete`错误,尝试手动删除目标文件也失败,提示`java.io.IOException`。经过分析,发现问题是由于`sys-info.log`文件被其他进程占用。解决方法是关闭IDEA和相关Java进程,清理隐藏的Java进程后重新尝试Maven clean操作。最终问题得以解决。总结:遇到此类问题时,可以通过任务管理器清理相关进程或重启电脑来解决。
|
2月前
|
存储 缓存 安全
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见。本文介绍了使用 `File.createTempFile` 方法和自定义创建临时文件的两种方式,详细探讨了它们的使用场景和注意事项,包括数据缓存、文件上传下载和日志记录等。强调了清理临时文件、确保文件名唯一性和合理设置文件权限的重要性。
212 2
|
2月前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
90 4