Java 簡單TCP文件傳輸

服務端

package TCP;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCP_File_Server {
    public static void main(String[] args) throws Exception {
        /**
         * 建立服務端套接字
         */
        ServerSocket ss = new ServerSocket();
        
        /**
         * 綁定指定端口
         */
        ss.bind(new InetSocketAddress(12345));
        System.out.println("《《《《網盤開始運行》》》》");
        /**
         * 監聽並接受客戶端socket鏈接,並返回一個socket
         */
        
        /**
         * 持續接收客戶端發來的信息,並交給線程處理
         */
        while(true) {
            Socket socket = ss.accept();
            new Thread(new UpLoad(socket)).start();
        }
    }
}

class UpLoad implements Runnable{
    
    private Socket socket = null;
    
    public UpLoad(Socket socket) {
        this.socket = socket;
    }
    
    @Override
    public void run() {

        OutputStream out = null;
        try {
            // 建立文件輸入流,接收客戶端的socket中的文件流
            InputStream in = socket.getInputStream();
            /**
             * 獲取文件名長度
             * 文件格式:文件名長度(數字)\r\文件名\r\n文件內容\r\n
             * 獲取文件名 - 讀到第一個回車換行以前 截取出文件名的長度 接着讀取這個長度的字節 就是文件名
             * 讀取數據 直到遇到第一個回車換行
             * 每次從流中讀取一個字節 轉成字符串 拼到line上 只要line還不是\r\n結尾 就重複這個過程
             */
            String line1 = "";
            byte[] by1 = new byte[1];
            while(!line1.endsWith("\r\n")) {
                in.read(by1);
                String str = new String(by1);
                line1 += str;
            }
            /**
             * 1.讀到長度,去掉\r\n就是文件名字的長度
             * 2.parseInt():做用是將可分析的字符串轉化爲整數。
             * 3.substring():返回一個新字符串,它是此字符串的一個子字符串。
             */
            int len1 = Integer.parseInt(line1.substring(0, line1.length() - 2));
            /**
             * 1.讀取文件名
             * 2.先建立一個長度和文件名長度相等的字節數組,用來存放文件名
             * 3.read(data):從輸入流中讀取必定數量的字節,並將其存儲在緩衝區數組 data 中
             *      data數組有多大,就在in輸入流裏面讀取多少內容,並將內容存放在data數組裏面
             */
            byte[] data = new byte[len1];
            in.read(data);
            String fileName = new String(data);
            
            // 獲取文件內容字節長度
            String line2 = "";
            byte[] by2 = new byte[1];
            while(!line2.endsWith("\r\n")) {
                in.read(by2);
                String str = new String(by2);
                line2 += str;
            }
            int len2 = Integer.parseInt(line2.substring(0, line2.length() - 2));
            
            // 建立輸文件出流,指定文件輸出地址
            String path = "E:/" + fileName;
            out = new FileOutputStream(path);
            // 獲取文件內容字節
            // 流對接
            byte[] by3 = new byte[len2];
            in.read(by3);
            out.write(by3);
            
            System.out.println("接受到來自"+socket.getInetAddress().getHostAddress()+"上傳的文件"+path);
            
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            // 關閉資源
            // 關閉輸出流
            try {
                if(out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                out = null;
            }
            // 關閉socket
            try {
                if(socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                socket = null;
            }
        }
    }
}

客戶端

package TCP;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Scanner;

public class TCP_File_Client {
    public static void main(String[] args) {
        Scanner scan = null;
        InputStream in = null;
        Socket socket = null;
        
        try {
            /**
             * 1.掃描控制檯接收文件路徑名
             *   建立一個file引用,指向一個新的File對象,並給文件賦予地址
             */
            System.out.println("請輸入要傳輸文件的路徑:");
            scan = new Scanner(System.in);
            String path = scan.nextLine();
            File file = new File(path);
            
            /**
             * 2.判斷文件是文本文件而不是文件夾而且路徑存在
             *  exists():判斷文件是否存在
             *  isFile():判斷是否是文件 
             */
            if(file.exists() && file.isFile()) {
                
                /**
                 * 3.建立文件輸入流,發送文件 
                 *   將文件輸入的內容都放在file裏面
                 */
                in = new FileInputStream(file);
                
                /**
                 * Socket 這個類實現客戶端套接字(也稱爲「套接字」)。套接字是兩臺機器間通訊的端點。
                 *
                 * 4.建立客戶端套接字
                 */
                socket = new Socket();
                //InetSocketAddress Inets = new InetSocketAddress("127.0.0.1", 12345);
                
                /**
                 * 5.鏈接TCP服務器
                 *       肯定服務端的IP和端口號
                 */
                socket.connect(new InetSocketAddress("127.0.0.1", 12345));
                
                /**
                 * 6.獲取到客戶端的輸出流
                 *   OutputStream     getOutputStream()
                 *                         返回此套接字的輸出流。 
                 */
                OutputStream out = socket.getOutputStream();
                
                /**
                 * 7.向服務器發送文件
                 *   本身定義了一個協議來解決粘包現象,獲取文件名
                 *   7.1.咱們先將文件中的內容讀取出來,放到file裏面
                 *   7.2.先讀文件名  file.getName()
                 *   7.3.將文件名轉換成字節  file.getName().getBytes()
                 *   7.4.獲取文件名的字節的長度  file.getName().getBytes().length
                 *   7.5.再在文件名長度的後面加上  \r\n 做爲標識符
                 */
                // 向服務器發送[文件名字節長度 \r\n]
                out.write((file.getName().getBytes().length + "\r\n").getBytes());
                // 向服務器發送[文件名字節]
                out.write(file.getName().getBytes());
                // 向服務器發送[文件字節長度\r\n]
                out.write((file.length() + "\r\n").getBytes());
                // 向服務器發送[文件字節內容]
                byte[] data = new byte[1024];
                int i = 0;
                while((i = in.read(data)) != -1) {
                    out.write(data, 0, i);
                }
                
            }else {
                System.out.println("文件不存在或者一個文件~~");
            }
        } catch (Exception e) {
            
            e.printStackTrace();
        }finally {
            /**
             * 關閉Scanner,文件輸入流,套接字
             * 套接字裝飾了輸出流,因此不用關閉輸出流
             */
            if(scan != null) {
                scan.close();
            }
            try {
                if(in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                // 強制將輸入流置爲空
                in = null;
            }
            try {
                if(socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                // 強制釋放socket
                socket = null;
            }
            
        }
        System.out.println("文件傳輸完畢");
    }
}
相關文章
相關標籤/搜索