最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?NIO實(shí)戰(zhàn)之多人聊天室

 更新時(shí)間:2021年11月24日 11:29:10   作者:紅字V  
這篇文章主要為大家詳細(xì)介紹了Java?NIO實(shí)戰(zhàn)之多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了Java NIO實(shí)戰(zhàn)之多人聊天室的具體代碼,供大家參考,具體內(nèi)容如下

NIO服務(wù)端

public class NioServer {

    /**
     * 啟動(dòng)
     */
    public void start() throws IOException {
        /**
         * 1. 創(chuàng)建Selector
         */
        Selector selector = Selector.open();
        /**
         * 2. 通過ServerSocketChannel創(chuàng)建channel通道
         */
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        /**
         * 3. 為channel通道綁定監(jiān)聽端口
         */
        serverSocketChannel.bind(new InetSocketAddress(8000));
        /**
         * 4. **設(shè)置channel為非阻塞模式**
         */
        serverSocketChannel.configureBlocking(false);
        /**
         * 5. 將channel注冊(cè)到selector上,監(jiān)聽連接事件
         */
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服務(wù)器啟動(dòng)成功!");

        /**
         * 6. 循環(huán)等待新接入的連接
         */
        for (;;) { // while(true) c for;;
            /**
             * TODO 獲取可用channel數(shù)量
             */
            int readyChannels = selector.select();

            /**
             * TODO 為什么要這樣!???
             */
            if (readyChannels == 0) continue;

            /**
             * 獲取可用channel的集合
             */
            Set<SelectionKey> selectionKeys = selector.selectedKeys();

            Iterator iterator = selectionKeys.iterator();

            while (iterator.hasNext()) {
                /**
                 * selectionKey實(shí)例
                 */
                SelectionKey selectionKey = (SelectionKey) iterator.next();

                /**
                 * **移除Set中的當(dāng)前selectionKey**
                 */
                iterator.remove();

                /**
                 * 7. 根據(jù)就緒狀態(tài),調(diào)用對(duì)應(yīng)方法處理業(yè)務(wù)邏輯
                 */
                /**
                 * 如果是 接入事件
                 */
                if (selectionKey.isAcceptable()) {
                    acceptHandler(serverSocketChannel, selector);
                }

                /**
                 * 如果是 可讀事件
                 */
                if (selectionKey.isReadable()) {
                    readHandler(selectionKey, selector);
                }
            }
        }
    }

    /**
     * 接入事件處理器
     */
    private void acceptHandler(ServerSocketChannel serverSocketChannel,
                               Selector selector)
            throws IOException {
        /**
         * 如果要是接入事件,創(chuàng)建socketChannel
         */
        SocketChannel socketChannel = serverSocketChannel.accept();

        /**
         * 將socketChannel設(shè)置為非阻塞工作模式
         */
        socketChannel.configureBlocking(false);

        /**
         * 將channel注冊(cè)到selector上,監(jiān)聽 可讀事件
         */
        socketChannel.register(selector, SelectionKey.OP_READ);

        /**
         * 回復(fù)客戶端提示信息
         */
        socketChannel.write(Charset.forName("UTF-8")
                .encode("你與聊天室里其他人都不是朋友關(guān)系,請(qǐng)注意隱私安全"));
    }

    /**
     * 可讀事件處理器
     */
    private void readHandler(SelectionKey selectionKey, Selector selector)
            throws IOException {
        /**
         * 要從 selectionKey 中獲取到已經(jīng)就緒的channel
         */
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();

        /**
         * 創(chuàng)建buffer
         */
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        /**
         * 循環(huán)讀取客戶端請(qǐng)求信息
         */
        String request = "";
        while (socketChannel.read(byteBuffer) > 0) {
            /**
             * 切換buffer為讀模式
             */
            byteBuffer.flip();

            /**
             * 讀取buffer中的內(nèi)容
             */
            request += Charset.forName("UTF-8").decode(byteBuffer);
        }

        /**
         * 將channel再次注冊(cè)到selector上,監(jiān)聽他的可讀事件
         */
        socketChannel.register(selector, SelectionKey.OP_READ);

        /**
         * 將客戶端發(fā)送的請(qǐng)求信息 廣播給其他客戶端
         */
        if (request.length() > 0) {
            // 廣播給其他客戶端
            broadCast(selector, socketChannel, request);
        }
    }

    /**
     * 廣播給其他客戶端
     */
    private void broadCast(Selector selector,
                           SocketChannel sourceChannel, String request) {
        /**
         * 獲取到所有已接入的客戶端channel
         */
        Set<SelectionKey> selectionKeySet = selector.keys();

        /**
         * 循環(huán)向所有channel廣播信息
         */
        selectionKeySet.forEach(selectionKey -> {
            Channel targetChannel = selectionKey.channel();

            // 剔除發(fā)消息的客戶端
            if (targetChannel instanceof SocketChannel
                    && targetChannel != sourceChannel) {
                try {
                    // 將信息發(fā)送到targetChannel客戶端
                    ((SocketChannel) targetChannel).write(
                            Charset.forName("UTF-8").encode(request));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 主方法
     * @param args
     */
    public static void main(String[] args) throws IOException {
        new NioServer().start();
    }

}

NIO客戶端

public class NioClient {

    /**
     * 啟動(dòng)
     */
    public void start(String nickname) throws IOException {
        /**
         * 連接服務(wù)器端
         */
        SocketChannel socketChannel = SocketChannel.open(
                new InetSocketAddress("127.0.0.1", 8000));

        /**
         * 接收服務(wù)器端響應(yīng)
         */
        // 新開線程,專門負(fù)責(zé)來接收服務(wù)器端的響應(yīng)數(shù)據(jù)
        // selector , socketChannel , 注冊(cè)
        Selector selector = Selector.open();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
        new Thread(new NioClientHandler(selector)).start();

        /**
         * 向服務(wù)器端發(fā)送數(shù)據(jù)
         */
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
            String request = scanner.nextLine();
            if (request != null && request.length() > 0) {
                socketChannel.write(
                        Charset.forName("UTF-8")
                                .encode(nickname + " : " + request));
            }
        }

    }
    public static void main(String[] args) throws IOException {
//        new NioClient().start();
    }
}

客戶端線程,處理服務(wù)器端響應(yīng)的的消息

public class NioClientHandler implements Runnable {
    private Selector selector;

    public NioClientHandler(Selector selector) {
        this.selector = selector;
    }

    @Override
    public void run() {

        try {
            for (;;) {
                int readyChannels = selector.select();

                if (readyChannels == 0) continue;

                /**
                 * 獲取可用channel的集合
                 */
                Set<SelectionKey> selectionKeys = selector.selectedKeys();

                Iterator iterator = selectionKeys.iterator();

                while (iterator.hasNext()) {
                    /**
                     * selectionKey實(shí)例
                     */
                    SelectionKey selectionKey = (SelectionKey) iterator.next();

                    /**
                     * **移除Set中的當(dāng)前selectionKey**
                     */
                    iterator.remove();

                    /**
                     * 7. 根據(jù)就緒狀態(tài),調(diào)用對(duì)應(yīng)方法處理業(yè)務(wù)邏輯
                     */

                    /**
                     * 如果是 可讀事件
                     */
                    if (selectionKey.isReadable()) {
                        readHandler(selectionKey, selector);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 可讀事件處理器
     */
    private void readHandler(SelectionKey selectionKey, Selector selector)
            throws IOException {
        /**
         * 要從 selectionKey 中獲取到已經(jīng)就緒的channel
         */
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();

        /**
         * 創(chuàng)建buffer
         */
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        /**
         * 循環(huán)讀取服務(wù)器端響應(yīng)信息
         */
        String response = "";
        while (socketChannel.read(byteBuffer) > 0) {
            /**
             * 切換buffer為讀模式
             */
            byteBuffer.flip();

            /**
             * 讀取buffer中的內(nèi)容
             */
            response += Charset.forName("UTF-8").decode(byteBuffer);
        }

        /**
         * 將channel再次注冊(cè)到selector上,監(jiān)聽他的可讀事件
         */
        socketChannel.register(selector, SelectionKey.OP_READ);

        /**
         * 將服務(wù)器端響應(yīng)信息打印到本地
         */
        if (response.length() > 0) {
            System.out.println(response);
        }
    }
}

我們定義三個(gè)客戶端,模擬三個(gè)用戶在聊天室發(fā)送消息

public class AClient {

    public static void main(String[] args)
            throws IOException {
        new NioClient().start("AClient");
    }
}

public class BClient {

    public static void main(String[] args)
            throws IOException {
        new NioClient().start("BClient");
    }
}

public class CClient {

    public static void main(String[] args)
            throws IOException {
        new NioClient().start("CClient");
    }

}

NIO 聊天室到此結(jié)束

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用自定義注解和@Aspect實(shí)現(xiàn)責(zé)任鏈模式的組件增強(qiáng)的詳細(xì)代碼

    使用自定義注解和@Aspect實(shí)現(xiàn)責(zé)任鏈模式的組件增強(qiáng)的詳細(xì)代碼

    責(zé)任鏈模式是一種行為設(shè)計(jì)模式,其作用是將請(qǐng)求的發(fā)送者和接收者解耦,從而可以靈活地組織和處理請(qǐng)求,本文講給大家介紹如何使用自定義注解和@Aspect實(shí)現(xiàn)責(zé)任鏈模式的組件增強(qiáng),文中有詳細(xì)的代碼示例供大家參考,感興趣的同學(xué)可以借鑒一下
    2023-05-05
  • java調(diào)用7zip解壓壓縮包的實(shí)例

    java調(diào)用7zip解壓壓縮包的實(shí)例

    下面小編就為大家?guī)硪黄猨ava調(diào)用7zip解壓壓縮包的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • Spring 使用JavaConfig實(shí)現(xiàn)配置的方法步驟

    Spring 使用JavaConfig實(shí)現(xiàn)配置的方法步驟

    這篇文章主要介紹了Spring 使用JavaConfig實(shí)現(xiàn)配置的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 淺談java調(diào)用Restful API接口的方式

    淺談java調(diào)用Restful API接口的方式

    這篇文章主要介紹了淺談java調(diào)用Restful API接口的方式,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • 詳解Spring MVC自動(dòng)為對(duì)象注入枚舉類型

    詳解Spring MVC自動(dòng)為對(duì)象注入枚舉類型

    本篇文章主要介紹了Spring MVC自動(dòng)為對(duì)象注入枚舉類型,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • Java編程實(shí)現(xiàn)直接插入排序代碼示例

    Java編程實(shí)現(xiàn)直接插入排序代碼示例

    這篇文章主要介紹了Java編程實(shí)現(xiàn)直接插入排序代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • java短路邏輯運(yùn)算符實(shí)例用法詳解

    java短路邏輯運(yùn)算符實(shí)例用法詳解

    在本篇文章里小編給大家分享的是一篇關(guān)于java短路邏輯運(yùn)算符實(shí)例用法內(nèi)容,有需要的朋友們可以學(xué)習(xí)參考下。
    2021-04-04
  • Spring cloud alibaba之Ribbon負(fù)載均衡實(shí)現(xiàn)方案

    Spring cloud alibaba之Ribbon負(fù)載均衡實(shí)現(xiàn)方案

    Spring cloud Ribbon是基于Netflix Ribbon實(shí)現(xiàn)的一套客戶端的負(fù)載均衡工具,Ribbon客戶端提供一系列完善的配置,如超時(shí)、重試等,Ribbon也可以實(shí)現(xiàn)自己的負(fù)載均衡算法,感興趣的朋友跟隨小編一起看看吧
    2021-07-07
  • Java?spring?通過注解方式創(chuàng)建對(duì)象的示例詳解

    Java?spring?通過注解方式創(chuàng)建對(duì)象的示例詳解

    這篇文章主要介紹了java?spring?通過注解方式創(chuàng)建對(duì)象,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • Spring Cache框架應(yīng)用介紹

    Spring Cache框架應(yīng)用介紹

    我們一定聽說過"緩存無敵"的話,特別是在大型互聯(lián)網(wǎng)公司,"查多寫少"的場景屢見不鮮。Spring Cache是作用在方法上的,其核心思想是,當(dāng)我們?cè)谡{(diào)用一個(gè)緩存方法時(shí)會(huì)把該方法參數(shù)和返回結(jié)果作為一個(gè)鍵值對(duì)存在緩存中
    2022-09-09

最新評(píng)論

福建省| 昌江| 正镶白旗| 北安市| 辛集市| 偃师市| 朔州市| 罗田县| 宿迁市| 赤壁市| 松潘县| 句容市| 宝兴县| 垦利县| 肥乡县| 睢宁县| 湛江市| 武宣县| 阿克| 龙岩市| 清徐县| 铁岭县| 衢州市| 共和县| 新蔡县| 新丰县| 蓬莱市| 武川县| 濮阳县| 河南省| 安溪县| 成都市| 正阳县| 绿春县| 交城县| 沾化县| 克什克腾旗| 茌平县| 甘泉县| 长垣县| 玉屏|