网络编程——实验一:基于TCPUDP的网络文件服务
目錄
?
前言:本篇文章不提供知識點教學,只提供一些常見問題的解決方法和實現實驗要求的學習路徑
1 java IO
2 java Socket
2.1 創建簡單的TCP連接
2.2 創建簡單的UDP連接
2.3 創建多線程服務器+多用戶連接服務器
3 文件傳輸
3.1 UDP文件傳輸
3.2 TCP文件傳輸
4 實現實驗要求
3.1 簡述實驗要求
3.2 創建TCP和UDP的服務器端
3.2 使用TCP傳輸用戶命令,使用UDP傳輸文件
3.3 文件目錄管理
?
前言:本篇文章不提供知識點教學,只提供一些常見問題的解決方法和實現實驗要求的學習路徑
?
1 java IO
?
2 java Socket
?
2.1 創建簡單的TCP連接
?
2.2 創建簡單的UDP連接
?
2.3 創建多線程服務器+多用戶連接服務器
?
3 文件傳輸
?
3.1 UDP文件傳輸
?
3.1.1 服務器端作為發送端,客戶端作為接收端
?
3.1.1.1 問題分解
指定...
關于服務器端如何獲取客戶端的host和port:
已否決:通過客戶端連接
嘗試:UDP客戶端發送一份數據給UDP服務器端,通過dp.getAddress()和dp.getPort()獲取UDP客戶端的端口號
?
3.1.1.2 關鍵問題
問題1:指定文件的大小(其實沒必要,不用指定文件大小,每次按固定的大小循環傳輸直到傳完所有的數據即可)
問題如下圖所示:
服務器端代碼:
?pw.println("文件大小:" + is.available() + " bytes"); // 告訴客戶端要接收的文件的大小(單位:byte)客戶端代碼:
?int length = Integer.parseInt(br.readLine()); // 獲取服務器端傳來的文件的大小(單位:byte)由于輸入不是純數字,因此String不能順利轉換為int
解決方案:
? // 預定義bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));// 服務器端is = new FileInputStream(new File(BASE_PATH + fileName));byte[] b = new byte[is.available()];System.out.println(is.available());pw.println(is.available()); // 告訴客戶端要接收的文件的大小(單位:byte) ? // 預定義br = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 客戶端int length = Integer.parseInt(br.readLine()); // 獲取服務器端傳來的文件的大小(單位:byte)System.out.println("文件大小為:" + length + " bytes");byte[] b = new byte[length];問題2:文件過大,不能一次傳輸完
問題描述:
解決方案:分段傳輸
代碼如下:
? // 服務器端is = new FileInputStream(new File(BASE_PATH + fileName));pw.println(is.available()); // 告訴客戶端要接收的文件的大小(單位:byte)byte[] b = new byte[BYTE_LEN];// 創建UDP數據報while (is.read(b) != -1) {DatagramPacket dp = new DatagramPacket(b, b.length, socketAddress);dgSocket.send(dp);System.out.println("傳輸文件中...");TimeUnit.MICROSECONDS.sleep(100); // 限制傳輸速度}System.out.println("文件發送成功"); ? // 客戶端os = new FileOutputStream(new File(BASE_PATH + fileName));byte[] b = new byte[BYTE_LEN];DatagramPacket dp = new DatagramPacket(b, b.length);int length = Integer.parseInt(br.readLine()); // 獲取服務器端傳來的文件的大小(單位:byte)while (length > 0) {// 接收數據dgSocket.receive(dp);os.write(b, 0, b.length);os.flush();System.out.println("接收文件中...");length -= BYTE_LEN;}?
問題3:文件名輸入錯誤(系統在該目錄下找不到該文件),未使用try catch語句捕捉錯誤
問題描述:
解決方案:
? // 服務器端try {is = new FileInputStream(new File(BASE_PATH + fileName));} catch(FileNotFoundException e) {System.out.println("不存在該文件,取消文件傳輸");pw.println("不存在該文件,取消文件傳輸");e.printStackTrace();return;} ? if( br.readLine().equals("不存在該文件,取消文件傳輸") ) {System.out.println("取消文件傳輸,結束本次通信");return;} else {System.out.println("文件已驗證存在");}衍生問題:由于已經調用過一次br.readLine(),后面又通過br.readLine()獲取文件長度。而readLine()會移動讀取指針,且服務器端只傳了一次length(通過pw.println(is.available());),因此在第二次調用br.readLine()的時候,客戶端獲取的內容為空,導致線程阻塞,文件傳輸不能正常進行。
解決方案:
? // 預定義PrintWriter pw = new PrintWriter(bw, true);// 服務器端// 傳兩次,因為客戶端br.readLine()使用了兩次【readLine()函數使用一次會移動讀取指針】pw.println(is.available()); // 告訴客戶端要接收的文件的大小(單位:byte)pw.println(is.available()); // 告訴客戶端要接收的文件的大小(單位:byte) ? // 預定義BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 客戶端if( br.readLine().equals("不存在該文件,取消文件傳輸") ) {System.out.println("取消文件傳輸,結束本次通信");return;} else {System.out.println("文件已驗證存在");}int length = Integer.parseInt(br.readLine()); // 獲取服務器端傳來的文件的大小(單位:byte)問題4:
?
3.1.2 客戶端作為發送端,服務器端作為接收端
?
3.2 TCP文件傳輸
?
4 實現實驗要求
?
3.1 簡述實驗要求
1) 復習Java I/O和Socket編程相關概念和方法;
2) 基于Java Socket TCP和UDP實現一個簡易的網絡文件服務程序,包含服務器端FileServer和客戶端FileClient;
3) 服務器端啟動時需傳遞root目錄參數,并校驗該目錄是否有效;
4) 服務器啟動后,開啟TCP:2021端口,UDP:2020端口,其中,TCP連接負責與用戶交互,UDP負責傳送文件;
5) 客戶端啟動后,連接指定服務器的TCP 2021端口,成功后,服務器端回復信息:“客戶端IP地址:客戶端端口號>連接成功”;
6) 連接成功后,用戶可通過客戶端命令行執行以下命令:
*[1] ls* 服務器返回當前目錄文件列表(<file/dir> name size)
*[2] cd * 進入指定目錄(需判斷目錄是否存在,并給出提示)
*[3] get * 通過UDP下載指定文件,保存到客戶端當前目錄下
*[4] bye* 斷開連接,客戶端運行完畢
7) 服務器端支持多用戶并發訪問,不用考慮文件過大或UDP傳輸不可靠的問題。
?
3.2 創建TCP和UDP的服務器端
?
3.2 使用TCP傳輸用戶命令,使用UDP傳輸文件
?
3.3 文件目錄管理
總結
以上是生活随笔為你收集整理的网络编程——实验一:基于TCPUDP的网络文件服务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国城市乞丐的五大经典表情
- 下一篇: 支付宝前端团队详解基于Node.js W