美文网首页
Socket编程多文件传输

Socket编程多文件传输

作者: Wpixel | 来源:发表于2018-06-26 17:19 被阅读0次

有子曰:“其为人也孝弟,而好犯上者,鲜矣;不好犯上,而好作乱者,未之有也。君子务本,本立而道生。孝弟也者,其为仁之本与!”

项目介绍:基于TCP协议实现多文件传输

将F盘test文件加下的所有文件发送到D盘下的FTP文件夹里

思路:socket发送单个文件,然后通过for循环来实现多文件传输。

简单做法(这里就简单说下思路,没实现):

_1) socket与服务器建立连接
_2) 然后发送一个文件
_3) socket断开
_4) 循环第一步

以上做法非常简单,但是socket建立连接时非常耗费资源的,如果有1000个文件要同时上传,那么socket就要与服务器建立1000次连接和1000次断开连接。写到这里我突然想到连接池,连接池也是一种提高的方法,虽然没有频繁的创建销毁,但是初始化的时候就占用了系统的资源,我何不创建一个socket用到系统报废呢。

高端做法:

所以如果你还不知道IO流的概念,那你就不能算是一个合格的程序员
我这里简单的说一下,大神绕道
当客户端想服务端发送数据的时候,是以byte[]的形式传输的,byte[]数组存放的是ASCII码
比如第一次发送的是"ABC",然后紧接着又发送"abcd"
那么服务端接受接受到的就是"ABCabcd"
所以流是不会断开的,既然是连在一起的,那么怎么区分呢?
那就要同时向服务端传一个长度
比如第一次发送的是"ABC",那么在发送"ABC"之前要让服务器知道我发送的内容长度,这里发送一个int类型的3
同理发送"abcd"之前也要发一个int类型的4,这是长度让,让服务器截取内容用的。
然后服务器解析的时候先获取前4个字节解析长度,然后通过长度来获取内容


_1) socket与服务器建立连接
_2) 然后for循环发送多个文件
_3) socket断开

从建立连接到发送完毕断开连接,从始至终都是只有一个socket。


先画一个流程图。(好丑啊)

OK不废话了,开始上代码

1.启动服务,等待客户端连接

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.plaf.basic.BasicInternalFrameTitlePane.MoveAction;

public class TcpSendFileServer {

    @SuppressWarnings("resource")
    public static void main(String[] args) {
        
        int port = 5555;
        ServerSocket server = null;
        Socket socket = null;
        try {
            server = new ServerSocket(port);
            System.out.println("======启动服务=======");
            
            String pathname = "D:\\FTP\\";
            File d = new File(pathname);
            if(!d.exists()){
                d.mkdir();
            }
            
            //使用线程池
            ExecutorService threadPool = Executors.newFixedThreadPool(100);
            
            while(true){
                socket = server.accept();
                InputStream in = socket.getInputStream();
                DataInputStream dis = new DataInputStream(in);
                int fileNum = dis.readInt();
                System.out.println("传输的文件总个数:"+fileNum);
                String[] fileNames = new String[fileNum];
                long[] fileSizes = new long[fileNum];
                for (int i = 0; i < fileNum; i++) {
                    fileNames[i] = dis.readUTF();
                    fileSizes[i] = dis.readLong();
                    System.out.println("文件名:"+fileNames[i]);
                    System.out.println("文件大小:"+fileSizes[i]);
                }
                int byteNum = 1024;
                Runnable runnable = () -> {
                    FileOutputStream fos = null;
                    try {
                        byte[] bytes = new byte[byteNum]; 
                        //储存剩下的字节
                        byte[] surplusbytes = new byte[byteNum]; 
                        int length = 0;
                        //文件剩余大小
                        int leftLen = 0;
                        int writeLen  = 0;
                        boolean flog = true;
                        int num = 0;
                        long totalWriteLens = 0;
                        
                        //没用的变量
                        int testLen = 0;
                        int pointLen = 0;
                        while(((length = dis.read(bytes, 0, bytes.length)) != -1 || surplusbytes[0] != 0) && num < fileNum){
                            if(flog){
                                System.out.println("开始接受文件"+(num+1));
                                File file = new File(pathname+fileNames[num]);
                                fos = new FileOutputStream(file);
                                totalWriteLens = 0;
                                testLen = 0;
                                flog = false;   
                                if((num+1) == 6){
                                    System.out.println("=-----------------");
                                }
                            } 
                            if(length >= (int)fileSizes[num] || surplusbytes[0] != 0){
                                if(surplusbytes[0] != 0){
                                    testLen = surplusbytes.length - pointLen;
                                    if((int)fileSizes[num] >= testLen){
                                        fos.write(surplusbytes, 0, testLen);
                                        fos.flush();
                                        surplusbytes = new byte[byteNum];
                                        totalWriteLens += testLen;
                                    }else{
                                        fos.write(surplusbytes, 0, (int)fileSizes[num]);
                                        fos.flush();
                                        leftLen = surplusbytes.length - (int)fileSizes[num];
                                        move(surplusbytes, surplusbytes, (int)fileSizes[num] , leftLen);
                                        testLen = 0;
                                        flog = true;
                                    }
                                }
                                if(length >= (int)fileSizes[num] - testLen){
                                    fos.write(bytes, 0, (int)fileSizes[num] - testLen);
                                    fos.flush();
                                    pointLen = (int)fileSizes[num] - testLen;
                                    leftLen = bytes.length - (int)fileSizes[num];
                                    move(surplusbytes, bytes, (int)fileSizes[num] , leftLen);
                                }else{
                                    if(surplusbytes[0] != 0 && !flog){
                                        fos.write(surplusbytes, 0, (int)fileSizes[num]);
                                        surplusbytes = new byte[byteNum];
                                    }
                                    if(!flog){
                                        fos.write(bytes);
                                        surplusbytes = new byte[byteNum];
                                    }
                                    fos.flush();
                                    totalWriteLens += length;
                                }
                                if(surplusbytes[0] != 0 || num >= fileNum){
                                    flog = true;
                                    num ++;
                                }
                                
                            }else{
                                if((fileSizes[num] - totalWriteLens) / length < 1){
                                    length = (int)(fileSizes[num] - totalWriteLens);
                                }
                                if(surplusbytes[0] != 0){
                                    fos.write(surplusbytes, 0, leftLen);
                                    fos.flush();
                                    surplusbytes = new byte[byteNum];
                                }
                                fos.write(bytes, 0, length);
                                fos.flush();
                                leftLen = bytes.length - length;
                                pointLen = length;
                                move(surplusbytes, bytes, length, leftLen);
                                if(surplusbytes[0] != 0){
                                    flog = true;
                                    num ++;
                                }
                                totalWriteLens += length;
                            }
                        }
                        System.out.println("==========文件传输完毕===========");
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if(fos != null){
                                fos.close();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                };
                threadPool.execute(runnable);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            
        }
    }
    
    
    /**
     * 
     * @param surplusbytes
     * @param bytes
     * @param length 已经使用的个数
     * @param leftLen 剩下需要转移的数组个数
     */
    public static void move(byte[] surplusbytes, byte[] bytes, int length, int leftLen){
        for (int i = 0; i < leftLen; i++) {
            if(bytes[length+i] != 0){
                surplusbytes[i] = bytes[length+i];
            }
        }
    }
}

2.客户端建立一个连接发送多文件

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Socket;

public class TcpSendFileClient {

    public static int port = 5555;
    public static String host = "localhost";
    public static Socket socket = null;

    @SuppressWarnings("resource")
    public static void main(String[] args) {
        //创建socket连接
        createSocket();
        try {
            //发送文件的发放,需要文件价路径
            sendMultipleFile( "F:\\Test");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭socket连接
            closeSocket();
        }
    }

    public static void sendMultipleFile(String path) throws Exception{
        String[] fileNames = getFileName(path);
        sendSingleFile(path, fileNames);
    }

    public static String[] getFileName(String path){
        File file = new File(path);
        return file.list();
    }

    public static File[] createFile(String path, String[] pathname){
        File[] files = new File[pathname.length];
        try {
            for (int i = 0; i < pathname.length; i++) {
                File file = new File(path+"\\"+pathname[i]);
                if(file.exists() && file.isFile()){
                    file.createNewFile();
                    files[i] = file;
                }
            }
            return files;
            } catch (IOException e) {
            e.printStackTrace();
        }
        return files;
    }

    public static void sendSingleFile(String path, String[] pathName) throws Exception{
        File[] file = createFile(path, pathName);
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

        dos.writeInt(file.length);
        dos.flush();
        //将文件名和文件长度先发送过去
        for (int i = 0; i < file.length; i++) {
            System.out.println(file.length+"=="+file[i].getName()+"=="+file[i].length());
            dos.writeUTF(file[i].getName());
            dos.flush();
            dos.writeLong(file[i].length());
            dos.flush();
        }
    
        System.out.println("开始发送文件...");

        byte[] bytes = new byte[1024];   
        int length = 0;
        //发送文件内容
        for (int i = 0; i < file.length; i++) {
            FileInputStream fis = new FileInputStream(file[i]);
            while((length = fis.read(bytes, 0, bytes.length)) != -1){
                dos.write(bytes, 0, length);
                dos.flush();
            }
        }
        System.out.println("文件发送完毕...");
    }

    public static void createSocket(){
        try {
            socket = new Socket(host, port);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void closeSocket(){
        try {
            if(socket != null){
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.运行结果

客户端打印信息
4==1.jpg==161236
4==2.jpg==182327
4==3.jpg==42138
4==4.jpg==73057
开始发送文件...
文件发送完毕...
======== 文件传输结束 ========

服务端打印信息
======启动服务=======
传输的文件总个数:4
文件名:1.jpg
文件大小:161236
文件名:2.jpg
文件大小:182327
文件名:3.jpg
文件大小:42138
文件名:4.jpg
文件大小:73057
开始接受文件1
开始接受文件2
开始接受文件3
开始接受文件4
==========文件传输完毕===========

成功将4个文件传送过去了



作者是一名自由程序员,住在上海,喜欢音乐、小说、旅行、以及编程。

P.S. 如果您喜欢这篇文章并且希望学习编程技术的话,请关注一下

相关文章

  • Socket编程多文件传输

    有子曰:“其为人也孝弟,而好犯上者,鲜矣;不好犯上,而好作乱者,未之有也。君子务本,本立而道生。孝弟也者,其为仁之...

  • Go基础编程---网络(socket)编程

    socket编程 服务器编码---多协程和服务器通信 文件传输程序 go实现--聊天室---代码

  • 知识点

    网络编程 我项目中Socket是怎么实现IM通讯的;Socket通讯,怎么实现图片,大文件传输;http报文结构;...

  • 许世伟的Go语言基础 第五章总结

    第5章 网络编程 5.1 socket编程 以往socket编程: 建立socket:使用socket()函数。 ...

  • linux|Socket编程 简单文件传输

    Readme Server端在终端输入 Client端在终端输入 CODE Server Client qoute...

  • 网络编程

    python学习笔记-网络编程 socket编程: socket()函数:socket.socket([famil...

  • 简易ftp server搭建----获取主机IP地址

    学习了基本的socket编程之后, 想要自己搭建一个ftp用于电脑之间的文件传输. 在尝试阅读RFC959协议被虐...

  • TCP socket 编程

    TCP socket 编程 讲一下 socket 编程 步骤 使用 socket 模块 建立 TCP socket...

  • 网络编程

    网络 Socket 基于TCP协议的Socket编程 基于UDP协议的Socket编程

  • (三)即时通讯系列之UDPSocket

    即时通讯系列之Socket简介 转自他人 1. UDP Socket编程 先讲一讲UDP编程,因为比TCP要简单多...

网友评论

      本文标题:Socket编程多文件传输

      本文链接:https://www.haomeiwen.com/subject/dnxzeftx.html