1. 程式人生 > >2.1Java 阻塞式io程式設計

2.1Java 阻塞式io程式設計

Java 阻塞式io程式設計

執行流程

總體流程圖

1.Server

  1. 建立連線(ServerSocketChannel)
  2. 開啟埠(SocketAddress)並繫結bind()
  3. 迴圈監聽 1)等待請求連線serversocketchannel.accept() 【發生阻塞】 2)每個SocketChannel開啟執行緒讀取資料。

2.Client

  1. 開啟socketChannel
  2. 建立連線socketChannel.connect(地址,埠)
  3. 開始傳送和接受資料。

程式碼

Server

public class Server {
    public static void main(
String[] args) throws IOException { // 開啟Socket ServerSocketChannel serversocketchannel = ServerSocketChannel.open(); // 開啟埠 SocketAddress socketAddress = new InetSocketAddress(8080); // 監聽8080 埠進來的tcp連線 serversocketchannel.socket().bind(socketAddress); // 開啟迴圈監聽
while(true){ // 這裡會阻塞,直到有請求連線 SocketChannel socketChannel = serversocketchannel.accept(); // 開啟新的執行緒來處理這個請求,然後while迴圈監聽8080埠 SocketHandler handler = new SocketHandler(socketChannel); new Thread(handler).start(); } } }

SocketHandler處理資料

public class SocketHandler implements Runnable{

    private SocketChannel socketChannel;
    public SocketHandler(SocketChannel socketChannel){
        this.socketChannel = socketChannel;
    }
    public void run() {
//      堆空間中分配緩衝區
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        try {
//            將請求資料讀入Buffer中
            int num ;
//            如果有資料
            while ((num = socketChannel.read(buffer))>0){
//                讀取Buffer內容之前先flip一下
                // Buffer 切換為讀模式
                buffer.flip();
//               加快讀取速度
                byte[] bytes = new byte[num];
//                讀取資料
                buffer.get(bytes);
                String result = new String (bytes,"UTF-8");
                System.out.println("收到請求:"+result);
//                回覆客戶端
//                warp用於存放在byte陣列
                ByteBuffer writeBuffer = ByteBuffer.wrap(("我已經收到你的請求,你的請求內容是:" + result).getBytes());
                socketChannel.write(writeBuffer);
                buffer.clear();
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

client

public class Client {

    public static void main(String[] args) {
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.connect(new InetSocketAddress("localhost",8080));
//            傳送請求
            ByteBuffer buffer = ByteBuffer.wrap("test".getBytes());
            socketChannel.write(buffer);
//            獲取server響應
            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
            int num ;
            if((num = socketChannel.read(readBuffer))> 0 ){
                readBuffer.flip();
                byte[] result = new byte[num];
                readBuffer.get(result);
                String  demo = new String(result,"UTF-8");
                System.out.println("返回值:"+demo);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

結果展示和分析

執行結構 Server 在這裡插入圖片描述 client 在這裡插入圖片描述

阻塞io的缺點

  1. 每次連線都要新開執行緒(accept()方法開執行緒處理。)
  2. accept() 是一個阻塞操作,