Java之Socket上的Read操作阻塞問題

從Socket上讀取對端發過來的數據一般有兩種方法:
1)按照字節流讀取
[java] view plain copy
  1. BufferedInputStream in = new BufferedInputStream(socket.getInputStream());  
  2. int r = -1;  
  3. List<Byte> l = new LinkedList<Byte>();  
  4. while ((r = in.read()) != -1) {  
  5.     l.add(Byte.valueOf((byte) r));  
  6. }  

2)按照字符流讀取
[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));          
  2. String s;  
  3. while ((s = in.readLine()) != null) {  
  4.     System.out.println("Reveived: " + s);  
  5. }  

這兩個方法read()和readLine()都會讀取對端發送過來的數據,如果無數據可讀,就會阻塞直到有數據可讀。或者到達流的末尾,這個時候分別返回-1和null。
這個特性使得編程非常方便也很高效。
但是這樣也有一個問題,就是如何讓程序從這兩個方法的阻塞調用中返回。

總結一下,有這麼幾個方法:
1)發送完後調用Socket的shutdownOutput()方法關閉輸出流,這樣對端的輸入流上的read操作就會返回-1。
注意不能調用socket.getInputStream().close()。這樣會導致socket被關閉。
當然如果不需要繼續在socket上進行讀操作,也可以直接關閉socket。
但是這個方法不能用於通信雙方需要多次交互的情況。

2)發送數據時,約定數據的首部固定字節數爲數據長度。這樣讀取到這個長度的數據後,就不繼續調用read方法。

3)爲了防止read操作造成程序永久掛起,還可以給socket設置超時。
如果read()方法在設置時間內沒有讀取到數據,就會拋出一個java.net.SocketTimeoutException異常。
例如下面的方法設定超時3秒。
socket.setSoTimeout(3000);

感謝http://blog.csdn.net/fw0124/article/details/41227543

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章