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鏈接:點擊打開代碼

  這是我的微信公眾號,會不定時分享學習知識。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM