JAVA 基于TCP协议的一对一,一对多文件传输实现

  最近老师给我们上了多线程和TCP和UDP协议,其中一个要求就是我们用JAVA协议一个基于TCP和UDP这两种协议的一对一文件上传和一对多文件上传。

    然后我就开始分析TCP和UDP这两个协议的特点,发现TCP是流传输,抓住这一点就好实现了。

    现在我们需要解决一下几个问题,

    1.如何确定文件名称

    2.如何完成数据传输,并复原成原来的文件。

    解决方案就是,对象这是个好东西,因为TCP支持流传输的缘故,我们把每个文件对象化,这样我们就很容易实现基于TCP的多文件上传了。

    下面是文件对象代码:

    因为我考虑到了以后移植到web端也可以用,所以我添加了源地址这一栏。

 
package com.org.gjt.WebSocket.work1.entity;

import java.io.Serializable;

/**
 * @author gjt
 * @version 1.0
 * @Title: 文件实体类
 * @date 2018/5/24/10:45
 */
public class FileSetting implements Serializable{
    private static final long serialVersionUID = 613659699548582156L;
    /**
     * 文件名称
     */
    private String fileName;
    /**
     * 文件类型
     */
    private String fileType;
    /**
     * 文件大小
     */
    private long size;
    /**
     * 文件内容
     */
    private String stream;
    /**
     * 文件源地址
     */
    private String originPath;

    public String getOriginPath() {
        return originPath;
    }

    public void setOriginPath(String originPath) {
        this.originPath = originPath;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFileType() {
        return fileType;
    }

    public void setFileType(String fileType) {
        this.fileType = fileType;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public String getStream() {
        return stream;
    }

    public void setStream(String stream) {
        this.stream = stream;
    }
}

    其中需要注意的就是,我们需要对文件对象进行序列化。这是一种处理对象流的机制。原理的话网上很多。

    下面是TCP的配置实体类 

 
package com.org.gjt.WebSocket.work1.entity;

/**
 * @author gjt
 * @version 1.0
 * @Title: tcp连接实体
 * @date 2018/5/24/9:52
 */
public class TCPsetting {
    /**
     * 设置上传服务器
     */
    public final static String conAddr = "127.0.0.1";
    /**
     * 设置要上传的端口
     */
    public final static int port = 8888;
}

    到时候如果要放在服务器上只需要修改conAddr既可。

    下面是TCPSocket端的代码

    单独剥离出来的原因,主要是我希望能尽可能不让开发人员介入底层配置只需要填空即可。后面我还会对这个再一次封装。

package com.org.gjt.WebSocket.work1;

import com.org.gjt.WebSocket.work1.entity.TCPsetting;

import java.io.IOException;
import java.net.Socket;

/**
 * @author gjt
 * @version 1.0
 * @Title:  tcpSocketClient
 * @date 2018/5/24/11:10
 */
public class TcpSocketClient {
    /**
     * 建立socket连接
     * @return
     */
    public  Socket ConnectTcpClient(){
        Socket clientSocket = null;
        /**
         * 建立socket连接
         */
        try {
            clientSocket = new Socket(TCPsetting.conAddr,TCPsetting.port);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return clientSocket;
    }

    /**
     * 关闭连接
     * @param socket
     */
    public  void Close(Socket socket){
        try {
            socket.close();
            System.out.println("关闭成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

    下面是TCP协议的Client端

package com.org.gjt.WebSocket.work1;

import com.org.gjt.WebSocket.utils.FileUtils;
import com.org.gjt.WebSocket.work1.entity.FileSetting;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author gjt
 * @version 1.0
 * @Title: tcp一对一文件上传:客户端
 * @date 2018/5/24/9:50
 */
public class TCPSingleClient {

    /**
     * 建立客户端socket连接
     */
    private static TcpSocketClient conn  = new TcpSocketClient();

    /**
     * 设置文件信息
     */
    private static FileSetting file = new FileSetting();

    /**
     * 启动文件工具类
     */
    private static FileUtils fileUtils = new FileUtils();

    /**
     * 发送文件
     * @param path
     * @throws Exception
     */
    private static void SendFile(String path) throws Exception {
        Socket connect = conn.ConnectTcpClient();
        OutputStream os = connect.getOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);
        oos.writeObject(file);
        oos.writeObject(null);
        oos.flush();
        connect.shutdownOutput();
        String infoString=null;
        InputStream is = connect.getInputStream();
        BufferedReader br=new BufferedReader(new InputStreamReader(is));
        String info=null;
        while((info=br.readLine())!=null){
            System.out.println("服务器端的信息:" + info);
        }
        Scanner sc = new Scanner(System.in);
        sc.nextInt();
        connect.shutdownInput();
        oos.close();
        os.close();
        is.close();
        br.close();
        conn.Close(connect);
    }

    /**
     * 初始化文件并组装
     * @param path
     */
    private static void initFiles(String path) {
        File selectFile = new File(path);
        String name = selectFile.getName();
        String fileOriginPath = selectFile.getPath();
        String type = name.substring(name.lastIndexOf(".") + 1);
        String content = fileUtils.encryptToBase64(path);
        long size = selectFile.length();
        System.out.println("***************文件基本信息***************");
        System.out.println("name:"+name);
        System.out.println("fileOriginPath:"+fileOriginPath);
        System.out.println("type:"+type);
        System.out.println("content:"+content);
        System.out.println("size:"+size);
        System.out.println("***************文件基本信息***************");
        file.setFileName(name);
        file.setSize(size);
        file.setStream(content);
        file.setFileType(type);
        file.setOriginPath(fileOriginPath);
    }
    public static void main(String[] args) {
        String path = "E:\\webstromProject\\eduProject\\classWork\\test.jpg";
        initFiles(path);
        try {
            SendFile(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

       TCPserver端     

package com.org.gjt.WebSocket.work1;

import com.org.gjt.WebSocket.utils.FileUtils;
import com.org.gjt.WebSocket.work1.entity.FileSetting;
import com.org.gjt.WebSocket.work1.entity.TCPsetting;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author gjt
 * @version 1.0
 * @Title: 一对一上次:服务端
 * @date 2018/5/24/16:55
 */
public class TCPSingleServer {

    /**
     * 启动文件工具类
     */
    private static FileUtils fileUtils = new FileUtils();
    /**
     * 接受传输过来的对象
     */
    private static FileSetting fileSetting = new FileSetting();

    private static void StartService() throws Exception {
        Object obj = null;
        ServerSocket serverSocket = new ServerSocket(TCPsetting.port);
        System.out.println("服务器启动,等待客户端的连接。。。");
        Socket socket = serverSocket.accept();
        OutputStream os = null;
        PrintWriter pw = null;
        InputStream is = socket.getInputStream();
        ObjectInputStream ois=new ObjectInputStream(is);
        obj = ois.readObject();
        if (obj != null){
            System.out.println("接收到来自["+socket.getInetAddress().getHostAddress()+"]的文件");
            fileSetting = (FileSetting) obj;
            /**
             * 开始存储工作
             */
            File dir = new File("E:\\"+socket.getInetAddress().getHostAddress());
            if(!dir.exists()){
                dir.mkdir();
            }
            File file = new File(dir, socket.getInetAddress().getHostAddress()+fileSetting.getFileName());
            /**
             * 获取base64流转为指定文件
             */
            String stream = fileSetting.getStream();
            fileUtils.decryptByBase64(stream,file.getPath());
            System.out.println("保存成功");
        }
        os=socket.getOutputStream();
        pw=new PrintWriter(os);
        pw.println("传输完成!");
        pw.flush();
        socket.shutdownOutput();
        if(pw!=null){
            pw.close();
        }
        if(os!=null){
            os.close();
        }
        if(socket!=null){
            socket.close();
        }
    }

    public static void main(String[] args) {
        try {
            StartService();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

    这是基本代码,实现基于TCP的文件上传。

    修改成一对多也很简单,之后我会把两个版本的代码上传到我的github上去,有想法的大佬可以下载下来试试。

    关于修改成多文件上传,只需要在原来传输对象基础上修改成对象列表即可。

    git链接:点击打开代码

  这是我的微信公众号,会不定时分享学习知识。

猜你喜欢

转载自www.cnblogs.com/dddAndwerGuan/p/9112086.html