Java中Socket上的Read操作堵塞問題

weixin_34120274發表於2017-06-01
從Socket上讀取對端發過來的資料一般有兩種方法:
1)依照位元組流讀取
        BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
        int r = -1;
        List<Byte> l = new LinkedList<Byte>();
        while ((r = in.read()) != -1) {
            l.add(Byte.valueOf((byte) r));
        }

2)依照字元流讀取
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));        
        String s;
        while ((s = in.readLine()) != null) {
            System.out.println("Reveived: " + s);
        }

這兩個方法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);

相關文章