1. 程式人生 > 實用技巧 >關於java socket中的read方法阻塞問題

關於java socket中的read方法阻塞問題

客戶端:

public class TCPClient {
    public static void main(String[] args) throws IOException {
        FileInputStream fis=new FileInputStream("E:\\Trump.jpg");
        Socket socket=new Socket("127.0.0.1",8888);
        OutputStream os=socket.getOutputStream();
        byte[] bytes=new byte[1024];
        int len;
        while((len=fis.read(bytes))!=-1){
            //將讀取到的資料傳輸到客戶端與伺服器端之間的IO流
            os.write(bytes,0,len);
        }
       
        //讀伺服器回寫的資料
        InputStream is=socket.getInputStream();
        len=is.read(bytes);
        System.out.println(new String(bytes,0,len));

        socket.close();
        fis.close();
    }
}

伺服器端:

public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket server=new ServerSocket(8888);
        Socket socket=server.accept();
        InputStream is=socket.getInputStream();
        FileOutputStream fos=new FileOutputStream("E:\\Test\\Trump.jpg");

        int len;
        byte[] bytes=new byte[1024];
        while ((len=is.read(bytes))!=-1) {
            fos.write(bytes,0,len);
        }

        OutputStream os=socket.getOutputStream();
        os.write("檔案上傳完畢!".getBytes());
        fos.close();
        socket.close();

    }
}

這段程式碼執行以後會發現server類 read()方法發生了阻塞,經過查詢資料發現read()是一個阻塞函式(阻塞函式就是當這個函式不執行完,函式所線上程就一直停止在這裡不動。),如果客戶端沒有宣告斷開outputStream那麼它就會認為客戶端仍舊可能傳送資料,像read()這種阻塞讀取函式還有BufferedReader類種的 readLine()、DataInputStream種的readUTF()等。

解決方案:
Socket任意一端在呼叫完write()方法時呼叫shutdownOutput()方法關閉輸出流,這樣伺服器端的inputStream上的read操作就會返回-1, 這裡我們要注意下不能呼叫socket.getInputStream().close()。因為它會導致socket直接被關閉。 當然如果不需要繼續在socket上進行讀操作,也可以直接關閉socket。但是這個方法不能用於通訊雙方需要多次互動的情況。

原文:https://www.cnblogs.com/gaoqiri/p/10055610.html