NIO服務端和客戶端通訊demo

代碼轉自 https://www.jianshu.com/p/a9d030fec081java

服務端:緩存

package nio;

import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.channels.ServerSocketChannel; 
import java.nio.channels.SocketChannel; 
import java.util.*; 
import java.util.concurrent.ConcurrentHashMap; 
 
public class Server { 
    private Selector selector; 
    private ByteBuffer readBuffer = ByteBuffer.allocate(1024);//調整緩存的大小能夠看到打印輸出的變化 
    private ByteBuffer sendBuffer = ByteBuffer.allocate(1024);//調整緩存的大小能夠看到打印輸出的變化 
 
    String str;
    public void start() throws IOException {
        // 打開服務器套接字通道 
        ServerSocketChannel ssc = ServerSocketChannel.open(); 
        // 服務器配置爲非阻塞 
        ssc.configureBlocking(false); 
        // 進行服務的綁定 
        ssc.bind(new InetSocketAddress("localhost", 8001)); 
        
        // 經過open()方法找到Selector
        selector = Selector.open(); 
        // 註冊到selector,等待鏈接
        ssc.register(selector, SelectionKey.OP_ACCEPT);
        
        while (!Thread.currentThread().isInterrupted()) { 
            selector.select(); 
            Set<SelectionKey> keys = selector.selectedKeys(); 
            Iterator<SelectionKey> keyIterator = keys.iterator(); 
            while (keyIterator.hasNext()) { 
                SelectionKey key = keyIterator.next(); 
                if (!key.isValid()) { 
                    continue; 
                } 
                if (key.isAcceptable()) { 
                    accept(key); 
                } else if (key.isReadable()) { 
                    read(key); 
                } else if (key.isWritable()) {
                    write(key);
                }
                keyIterator.remove(); //該事件已經處理,能夠丟棄
            } 
        } 
    }

    private void write(SelectionKey key) throws IOException, ClosedChannelException {
        SocketChannel channel = (SocketChannel) key.channel();
        System.out.println("write:"+str);
        
        sendBuffer.clear();
        sendBuffer.put(str.getBytes());
        sendBuffer.flip();
        channel.write(sendBuffer);
        channel.register(selector, SelectionKey.OP_READ);
    } 
 
    private void read(SelectionKey key) throws IOException { 
        SocketChannel socketChannel = (SocketChannel) key.channel(); 
 
        // Clear out our read buffer so it's ready for new data 
        this.readBuffer.clear(); 
//        readBuffer.flip();
        // Attempt to read off the channel 
        int numRead; 
        try { 
            numRead = socketChannel.read(this.readBuffer); 
        } catch (IOException e) { 
            // The remote forcibly closed the connection, cancel 
            // the selection key and close the channel. 
            key.cancel(); 
            socketChannel.close(); 
            
            return; 
        } 
        
        str = new String(readBuffer.array(), 0, numRead);
        System.out.println(str);
        socketChannel.register(selector, SelectionKey.OP_WRITE);
    } 
 
    private void accept(SelectionKey key) throws IOException { 
        ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); 
        SocketChannel clientChannel = ssc.accept(); 
        clientChannel.configureBlocking(false); 
        clientChannel.register(selector, SelectionKey.OP_READ); 
        System.out.println("a new client connected "+clientChannel.getRemoteAddress()); 
    } 
 
    public static void main(String[] args) throws IOException { 
        System.out.println("server started..."); 
        new Server().start(); 
    } 
}

做者:御風逍遙
連接:https://www.jianshu.com/p/a9d030fec081
來源:簡書
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

客戶端:服務器

package nio;

import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.channels.SocketChannel; 
import java.util.Iterator; 
import java.util.Scanner; 
import java.util.Set; 
 
 
public class Client { 
 
    ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    
    public void start() throws IOException { 
        // 打開socket通道  
        SocketChannel sc = SocketChannel.open(); 
        //設置爲非阻塞
        sc.configureBlocking(false); 
        //鏈接服務器地址和端口
        sc.connect(new InetSocketAddress("localhost", 8001)); 
        //打開選擇器
        Selector selector = Selector.open(); 
        //註冊鏈接服務器socket的動做
        sc.register(selector, SelectionKey.OP_CONNECT); 
        
        Scanner scanner = new Scanner(System.in); 
        while (true) { 
            //選擇一組鍵,其相應的通道已爲 I/O 操做準備就緒。  
            //此方法執行處於阻塞模式的選擇操做。
            selector.select();
            //返回此選擇器的已選擇鍵集。
            Set<SelectionKey> keys = selector.selectedKeys(); 
            System.out.println("keys=" + keys.size()); 
            Iterator<SelectionKey> keyIterator = keys.iterator(); 
            while (keyIterator.hasNext()) { 
                SelectionKey key = keyIterator.next(); 
                keyIterator.remove(); 
                // 判斷此通道上是否正在進行鏈接操做。 
                if (key.isConnectable()) { 
                    sc.finishConnect(); 
                    sc.register(selector, SelectionKey.OP_WRITE); 
                    System.out.println("server connected..."); 
                    break; 
                } else if (key.isWritable()) { //寫數據 
                    System.out.print("please input message:"); 
                    String message = scanner.nextLine(); 
                    //ByteBuffer writeBuffer = ByteBuffer.wrap(message.getBytes()); 
                    writeBuffer.clear();
                    writeBuffer.put(message.getBytes());
                    //將緩衝區各標誌復位,由於向裏面put了數據標誌被改變要想從中讀取數據發向服務器,就要復位
                    writeBuffer.flip();
                    sc.write(writeBuffer); 
                    
                    //註冊寫操做,每一個chanel只能註冊一個操做,最後註冊的一個生效
                    //若是你對不止一種事件感興趣,那麼能夠用「位或」操做符將常量鏈接起來
                    //int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
                    //使用interest集合
                    sc.register(selector, SelectionKey.OP_READ);
                    sc.register(selector, SelectionKey.OP_WRITE);
                    sc.register(selector, SelectionKey.OP_READ);
                    
                } else if (key.isReadable()){//讀取數據
                    System.out.print("receive message:");
                    SocketChannel client = (SocketChannel) key.channel();
                    //將緩衝區清空以備下次讀取 
                    readBuffer.clear();
                    int num = client.read(readBuffer);
                    System.out.println(new String(readBuffer.array(),0, num));
                    //註冊讀操做,下一次讀取
                    sc.register(selector, SelectionKey.OP_WRITE);
                }
            } 
        } 
    } 
 
    public static void main(String[] args) throws IOException { 
        new Client().start(); 
    } 
}

做者:御風逍遙
連接:https://www.jianshu.com/p/a9d030fec081
來源:簡書
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索