2017-07-11 57 views
0

爲了理解套接字編程的概念,我創建了一個服務器和一個客戶端。客戶端將發送一個文件,服務器應該保存它的某個位置。 (即文件上傳)。使用ServerSocket和HTML客戶端上傳文件。卡在InputStream.read()

服務器:

package com.test.socket.server; 

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

public class WebServer { 

    public static void main(String[] args) throws IOException { 


     ServerSocket serverSocket = new ServerSocket(8081); 

     Socket socket = serverSocket.accept(); 

     System.out.println("Received request"); 


     InputStream inputStream = socket.getInputStream(); 

     OutputStream out = new FileOutputStream("yoyo.png"); 

     System.out.println("Reading...."); 

     byte[] bytes = new byte[16 * 1024]; 

     int count = 0; 
     while((count = inputStream.read(bytes)) > 0){ 
     System.out.print(". "); 
     out.write(bytes,0,count); 
     System.out.println("Some bytes are written"); 
     } 

     System.out.println("written...."); 

     socket.getOutputStream().write("Written.....".getBytes()); 

     out.close(); 
     inputStream.close(); 
     socket.close(); 
     serverSocket.close(); 


    } 

} 

Java客戶端如下:

package com.test.socket.client; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.Socket; 
import java.net.UnknownHostException; 

public class WebClient { 

    public static void main(String[] args) throws UnknownHostException, IOException { 

     Socket socket = null; 
     String host = "127.0.0.1"; 

     socket = new Socket(host, 8081); 

     ///home/renju/Desktop/frame.png 

     File file = new File("/home/renju/Desktop/frame.png"); 

     InputStream inputStream = new FileInputStream(file); 

     OutputStream os = socket.getOutputStream(); 

     byte[] bytes = new byte[16 * 1024]; 

     int count = 0; 
     while((count = inputStream.read(bytes)) > 0){ 
      os.write(bytes); 
     } 

     System.out.println("Sending...."); 

     os.close(); 
     inputStream.close(); 
     socket.close(); 
    } 

} 

這工作得很好,並上傳的文件寫入我的項目的根文件夾。 現在我將客戶端更改爲HTML頁面。

HTML:

<!DOCTYPE html> 
<html> 
<head> 
<meta charset="UTF-8"> 
<title>Insert title here</title> 
</head> 
<body> 

    <form action="http://127.0.0.1:8081/" method="POST"> 

     <input type="file" name="file" /> 
     <button type="submit" name="submit">Upload</button> 

    </form> 

</body> 
</html> 

enter image description here

這是不以同樣的方式作爲Java客戶端工作。出於某種原因,執行不會超出服務器代碼的out.write(bytes);

控制檯日誌..

Received request 
Reading.... 
. Some bytes are written 

是一個什麼可能的原因是什麼?

一個問題...

最終什麼,我想了解的是「多/表單數據」的目的,同時上傳文件(一次我得到了上面的代碼工作的,就是我是什麼計劃實驗)。如果有人可以給我一個提示,這將是非常有幫助的。

+0

爲了澄清,您可以上傳圖片,但是當你試圖上傳HTML頁面,出現這種情況? – finnrayment

+0

對不起,我看錯了。忽略已刪除的評論。 – finnrayment

+1

您的Java客戶端不會說HTTP,但是您的瀏覽器客戶端,所以您必須在服務器中實現HTTP。請參閱RFC 2616和後繼。太寬泛。 – EJP

回答

0

這工作正常。

不,它不。它在文件末尾寫入垃圾,並可能在其他地方寫入垃圾。你的複製循環應該是:

while((count = inputStream.read(bytes)) > 0){ 
    System.out.print(". "); 
    out.write(bytes, 0, count); 
} 

在服務器和客戶端。

由於某些原因,執行不會超出out.write(bytes);的服務器代碼。

實際上它在read()而不是write()中被阻止。這是因爲您現在正在獲取HTTP請求,特別是因爲HTTP Keepalive。請參閱RFC 2616和後繼。您編寫的服務器代碼會將所有HTTP標頭寫入目標文件,然後阻塞,直到客戶端瀏覽器釋放連接,這可能需要一段任意時間。需要解析頭,特別是Content-lengthContent-encoding標頭,並相應地處理請求的主體中,這意味着僅試圖讀取在Content-length給定的字節數,而不是讀出流的末尾,如果Content-encoding被分塊,則需要編寫一些非空白代碼。

+0

不,我驗證了使用java客戶端上傳的文件。沒事。但我遇到了HTML客戶端的問題。正如你所說的,它似乎在read()處被阻塞,但僅在循環中第一次寫入之後。我沒有使用java客戶端獲取HTTP請求?抱歉轉儲問題。儘管我已經使用了高級庫,但我仍然是Socket中的新手。 – Renjith

+1

否。複製代碼錯誤。你可能會非常幸運,但不要指望它。由於我陳述的原因,這是封鎖。您的Java客戶端不會說HTTP,但瀏覽器是。 – EJP

+0

「您的Java客戶端不會說HTTP,但瀏覽器是」....嗯..我懷疑...我必須這樣想。是mime類型進入圖片的地方嗎? – Renjith

-2

從Oracle文檔:

套接字是在網絡上運行的兩個 節目之間的雙向通信鏈路的一端點。套接字類用於表示客戶端程序和服務器程序之間的連接。 java.net包提供了兩個類 - Socket和ServerSocket,它們分別實現連接的客戶端和連接的服務器端 。

簡單的socket客戶端是:

Socket echoSocket = new Socket(hostName, portNumber); 
    PrintWriter out = 
     new PrintWriter(echoSocket.getOutputStream(), true); 
    BufferedReader in = 
     new BufferedReader(
      new InputStreamReader(echoSocket.getInputStream())); 

這裏使用的Socket構造函數需要計算機和您想要連接的端口號的名稱。

簡單的socket服務器:

ServerSocket serverSocket = new ServerSocket(portNumber); 
    Socket clientSocket = serverSocket.accept(); 
    PrintWriter out = 
     new PrintWriter(clientSocket.getOutputStream(), true); 
    BufferedReader in = new BufferedReader(
     new InputStreamReader(clientSocket.getInputStream())); 

ServerSocket是java.net的一個類,它提供一個獨立於系統的執行服務器端的。要接受來自客戶端ServerSocket連接不:

clientSocket = serverSocket.accept(); 
+0

嗯..這不回答我的問題。 – Renjith

+0

您無法使用「讀者」和「作家」正確傳輸圖片。 – EJP