2016-04-29 16 views
0

我使用ServerSocket在while循環中從客戶端獲取數據,它在第一次運行時工作,但在第二輪後失敗。ServerSocket在循環中沒有收到數據

我做了一些搜索,但仍然無法弄清楚發生了什麼事。

服務器端代碼

package com.gorilla.main; 

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

public class Server2 { 

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

     ServerSocket serverSocket = new ServerSocket(44444); 

     while(true){ 

     System.out.println("another round"); 

     Socket socket = serverSocket.accept(); 
     InputStream inputStream = socket.getInputStream(); 

     System.out.println("available: "+ inputStream.available()); 

     byte[] b = new byte[inputStream.available()]; 

     inputStream.read(b); 

     System.out.println(new String(b)); 
     System.out.println("======================="); 

     socket.close(); 
     } 
    } 
} 

克倫特端代碼

package com.gorilla.main; 

import java.io.IOException; 
import java.net.Socket; 
import java.net.UnknownHostException; 

public class Client2 { 

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

     Socket socket = new Socket("127.0.0.1", 44444); 
     String s = "Hello World"; 
     byte [] b = s.getBytes(); 
     socket.getOutputStream().write(b);; 
     socket.close(); 

    } 
} 

,並在服務器端控制檯輸出後,我跑了客戶端的3倍。

another round 
available: 11 
Hello World 
======================= 
another round 
available: 0 

======================= 
another round 
available: 0 

======================= 
another round 

任何建議,將不勝感激。謝謝。

回答

2

您使用InputStream.available()來調整您的緩衝區大小,這不是從套接字讀取的方式。您應該分配一個緩衝區(通常尺寸靜態,或也許配置)和環型

// server code 
byte[] buffer = new byte[4096]; 
int bytesRead; 
while ((bytesRead = in.read(buffer)) > -1) { 
    // do something 
} 

InputStream.available():

的Javadoc返回可讀取的字節數的估計值讀取(或 )從該輸入流中跳過而不被下一個 調用該輸入流的方法阻塞。下一個調用 可能是同一個線程或另一個線程。單個讀取或跳過 這麼多字節不會被阻塞,但可以讀取或跳過較少的字節。

如果協議是基於文本的,你可以用套接字的輸入流Scanner內,所以環形變成

while (scanner.hasNextLine()) { 
    String line = scanner.next(); 
} 
+0

它的工作原理。但是當inputStream.available()爲0時,爲什麼我可以從inputStream讀取一些內容?你有想法嗎? –

+0

並感謝您的回答! –

+0

你的用例不需要'available()'。只需閱讀(這是一個阻塞呼叫)並配置超時 – Raffaele