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("文件傳輸完畢"); } }