2013-12-18 51 views
3

我有簡單的C服務器和Java客戶端。我被從線發送服務器的文本文件行客戶端:如何確定讀取結束

do { 
     send(sockfd, line, strlen(line), 0); 
     printf("%s\n", line); 
    } while ((fgets(line, 100, fp)) != NULL); 

和Java客戶端與閱讀:

Client.getCl().getInputStream().read(inmsg); 
    do{    
     decoded = new String(inmsg, "UTF-8"); 
     System.out.println(decoded); 
    }while(Client.getCl().getInputStream().read(inmsg) > 0); 

我的問題是,我不知道如何發送「結束的閱讀「從服務器到客戶端。客戶端在上次讀取時凍結。我知道方法read()返回整數與接收字節的數量和-1,當沒有什麼可讀,0時,當緩衝區的長度爲零。將-1返回給客戶端的唯一解決方案是關閉服務器端的套接字,但我無法使用它。此外,我已經試過以下:
1)發送0長度在端發送方法告訴客戶端的,該長度是零:

send(sockfd, NULL, NULL, 0); 

2)定義的標誌併發送:

#define MSG_FIN 0x200 
#define MSG_EOR 0x0080 

並再次與兩個標誌:

send(sockfd, NULL, NULL, MSG_FIN); 
send(sockfd, NULL, NULL, MSG_EOR); 

任何人請幫助我在這裏做錯了什麼?謝謝

+2

我知道你說過你不能使用它,但_why_不能關閉服務器上的套接字嗎?如果你不願意關閉它,那不是說你以後會發送其他東西嗎?如果是這樣的話,那麼Java應該仍然可以閱讀,對吧? –

+0

您可能需要提前計算出要發送的字節數,並將數據前綴爲該數字,以便客戶端可以確定何時停止閱讀。它就像HTTP中的['Content-Length'頭部](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13)。 –

+0

如果您需要通過TCP連接發送不同的「消息」,那麼您需要實施和處理自己的應用程序級別的問題。 TCP並不關心這一點。 (雖然UDP不可靠,但它的不可靠性可能使它不適合你的使用情況,即不是媒體流或P2P) – millimoose

回答

5

如果要通過同一個TCP套接字發送間歇性數據,則需要對要發送的數據中發送的信息的邊界進行編碼。一個例子是發送帶有長度前綴的「數據包」,這樣一個數據包的接收方將讀取長度前綴所指的套接字數量。

+0

+1 reciver知道的唯一事情就是流的結束。如果你想知道「消息」,你需要添加一個協議來做到這一點。例如在每條消息前發送一個4字節的長度,以便知道要讀多少。 –

+0

現在我首先發送多行文件,然後將自己和客戶端讀取的次數與數字所說的次數相同。謝謝 –

0

您的閱讀器有兩個問題。你以爲你會一直讀取完整的緩衝區。除非您一次只讀取一個字節,否則不能假設這一點。您還假定您將始終讀取整個多字節字符,除非您從不使用多字節字符,否則這不太可能是真實的。

既然你正在寫文本,我建議你發送消息之間的新行,並閱讀文本流。

BufferedReader br = new BufferedReader(new InputStreamReader(
         Client.getCl().getInputStream(), "UTF-8")); 
for(String line; (line = br.readLine()) != null;) { 
    // process a whole line of text at once. e.g. 
    System.out.println(line); 
} 

這將解碼文本,讀取整行並處理任何多字節字符。