【java】網絡編程之BIO

BIO(阻塞式輸入輸出)是指在讀取輸入數據的時候會一直卡(阻塞)在那裏,在socket編程中會致使線程沒法處理其餘工做,除此以外,服務端等待accept鏈接也是阻塞式的,因此程序想繼續執行須要建立新的線程去處理其餘工做。
編程

注意socket鏈接並不表明鏈接能夠被處理,鏈接建立後,數據處理是須要線程來工做的,固然一個進程的可鏈接數也不是無限大的,超過最大鏈接數(操做系統限制或服務端限制)會致使沒法鏈接。網絡

相似阻塞式的飯店,新客人來了至關於和飯店創建一個socket鏈接,這只是鏈接能不能吃飯還要等待服務員給你下單,固然飯店要是滿了,新客人是進不去的。更糟糕的是,飯店只有一個服務員一直等着給第一個客人點菜下單,其餘客人都無論。客人也存在着相似問題,爲了和服務員維持這個鏈接,一直點菜或思考點什麼菜,卡在那裏。socket

----
ide

爲了解決上述線程阻塞的問題,只能建立新的線程來完成其餘工做,使程序得以繼續執行,下面使用兩個類(BioServer,BioClient)模擬一下BIO。this

 
 

public class BioServer {
  private ServerSocket serverSocket;
  public BioServer(int port,int backlog) throws IOException {
    this.serverSocket = new ServerSocket(port,backlog);
  }
  private void start() throws IOException {
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    while (true) {
      Socket socket = serverSocket.accept();
      System.out.println(String.format("a new client connect %s", socket.getPort()));
      executorService.submit(new BioServerHandler(socket));
    }
  }
  public static void main(String[] args) throws IOException {
    new BioServer(6000,3).start();
  }
}
class BioServerHandler implements Runnable {
  private Socket socket;
  public BioServerHandler(Socket socket) {
    this.socket = socket;
  }
  @Override
  public void run() {
    try (BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      PrintWriter pw = new PrintWriter(socket.getOutputStream())) {
      String msg;
      while ((msg = br.readLine()) != null) {
        System.out.println(String.format("server receive:%s", msg));
        pw.println(msg + " | " + new Date());
        pw.flush();
      }
    } catch (IOException e) {...}
  }
}spa

服務端使用線程池來處理客戶端鏈接,避免accept阻塞當前線程,程序沒法繼續,而在單個鏈接的線程處理中,又存在着阻塞式的read,因此線程池中的一個線程只能爲一個鏈接工做,沒法複用(除非有鏈接斷開線程釋放)。
----
public class BioClient {
  private Socket socket;
  public BioClient(String host,int port) throws IOException {
    this.socket = new Socket(host, port);
  }
  public void start({
    new Thread(()->{
        try(BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))){
        String msg;
        while((msg = br.readLine())!=null){
             System.out.println(String.format("client receive %s", msg));
        }
       } catch (IOException e) {...}finally {...}
     }).start();
    System.out.println("client enter msg: ");
    PrintWriter pw;
    while(true){
      try {
        pw = new PrintWriter(socket.getOutputStream());
        pw.println(new Scanner(System.in).next());
        pw.flush();
      } catch (IOException e) {...}
    }
}
  public static void main(String[] args) throws IOException {
     new BioClient("127.0.0.1",6000).start();  }}
客戶端爲了不阻塞讀取數據,建立新線程來處理數據讀取工做,在當前線程阻塞式等待系統輸入數據。以上就是阻塞式網絡編程BIO的demo,主要存在的問題是阻塞致使線程沒法複用。
相關文章
相關標籤/搜索