理解socket的阻塞


    從socket中得到一個輸入流InputStrean,然后從這個流中取數據,如果這個時候流里面的沒有數據,可能是服務還沒有發數據過來或發過來的數據也取完了,那么線程就會停在那里..直到服務器在發數據過來,從Socket的InputStream中取到了數據,這個線程才會向下走.所以當要和服務器交互通信的時候,就用一個while一真從Socket的流中數據取,流中的數據取完了就停在那里.等服務器在次發數據過來.---這就是阻塞的

    這個時候就有一個問題了,當我從Socket中的流中取數據時,如果服務器一直不發數據過來,也就是從Socket中得到的InputStream流中一直沒有數據,那么這個程序就一直停在從流中取數據的那一行.

    如果過了很長時間服務器還沒有數據發過來,就不等了,想讓程序繼續執行以后的代碼.這時只一個辦法,把服務器端關掉.客戶端檢測到這個Socket連接已斷開,就不會停在從流中取數據的代碼,而是執行下面的代碼.

    顯然以把服務器關掉的方式來讓Socket連接斷開有點不合適,所以我想到的辦法就是用多線程.讓線程A執行主代碼,線程B去從流中讀取數據,如果服務器又遲遲不發數據過來,又不關掉這個連接,那么線程B就一真讓它阻塞在那里.

    上面的所有,用一包話來概括:javaIO流是阻塞流,(JavaNIO(java new io非阻塞流,NIO這里沒有用到).

    這里在說說在ServerSocket是中的accept()方法也是一個阻塞方法,也就是如果沒有客戶端來連接,那么就線程就一直停在那里.直到有一個客戶端口連接了,才開始執行后面的代碼.

    從上面一點,可以看出如果要創建多客端的服務器,就要多次調用accept()方法,同要用多線程來做,線程A來一直循環執行accept().當有socket連接來過的時候就,創建一個新的線程來處理專門處理這個連接.

    到這里還沒有完,因為前面提到過,Socket連接里面的輸入輸出流也是阻塞的,如果這個Socket連好過后,客戶端和服務器遲遲不發數據,那么這個新創建的線程也會阻塞在那里,(除非這個新創建的線程里面不操作Socket里面的IO),為了阻止這種情況,就要像上面說的,在新創建的線程里面在新創建一個線程處理Socket里面的流的問題.

 

下面的程序的測試客戶端口建議用Sockettool的一個小軟件

public class SocketServer {

    public static void main(String[] args) throws IOException {
        ServerSocket serversocket = new ServerSocket(10088);
        Socket socket = serversocket.accept();// 同樣這也是一個阻塞方法
        //當第一個客戶端連接進來過后就會執行這句話,
        System.out.println("accept方法通過了....");
        //這個程序如果沒有第二個客戶端連進,那以下的代碼不會執行到的.
        Socket socket2 = serversocket.accept();
        System.out.println("accept2方法通過了....");
        InputStream instream = socket.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
        String line="";
        while (true){
            line=reader.readLine();
            if(line==null){
                System.out.println("line 為NULL 了");
                break;
            }
            System.out.println(line);
        }
        /**
         * 程序有一種情況可以執行到這里,就是socket客戶端口斷開.不是socket2斷開
         * 第一個連接斷開后line=reader.readLine();就不會在阻塞了.流中的數據讀
         * 完過后跳就跳出了while向下執行了.
         */
        System.out.println("程序結束了");
        
        // 關閉資源
        socket.close();
        serversocket.close();
    }
}

所在要做網絡編程就要到多線程.也這是多線程的一個理解:在多用戶和多網絡的的情況下,不可能為每一個用戶,和網絡請求都創建一個進程所以就有了線程.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM