ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NIO-实现聊天室

2022-04-16 18:02:07  阅读:138  来源: 互联网

标签:SocketChannel 聊天室 NIO 实现 Selector socketChannel new selector public


实现步骤:建立一个服务端和客户端

服务端

1、建立一个服务端

2、创建一个Selector选择器

3、创建一个Channel通道

4、绑定通道的监听端口

5、监听是否有新状态就去处理业务

public class TimServer {

    public static void main(String[] args) throws IOException {
        new TimServer().startServer();
    }

    public void startServer() throws IOException {
        //创建选择器
        Selector selector = Selector.open();
        //创建通道
        ServerSocketChannel ssc = ServerSocketChannel.open();
        //为通道绑定端口
        ssc.bind(new InetSocketAddress(8888));
        //设置为非阻塞通道
        ssc.configureBlocking(false);
        //把通道注册到选择器 加上感兴趣的事件
        ssc.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务器启动成功!");
        //循环监听
        while (true) {
            Set key = selector.selectedKeys();
            Iterator<SelectionKey> iterable = key.iterator();
            int readChannels = selector.select();
            while (iterable.hasNext()) {
                SelectionKey next = iterable.next();
                //移除当前集合的key
                iterable.remove();
                if (next.isAcceptable()) {
                    accept(ssc,selector);

                } else if (next.isReadable()) {
                    readable(selector,next);
                }
            }
        }

    }

    /**
     * 处理连接状态
     * */
    public  void accept(ServerSocketChannel serverSocketChannel,Selector selector) throws IOException {

        //接入ServerSocketChannel
        SocketChannel socketChannel = serverSocketChannel.accept();

        //设置为非阻塞模式
        socketChannel.configureBlocking(false);

        //把channel注册到选择器上
        socketChannel.register(selector,SelectionKey.OP_READ);

        //回复信息
        socketChannel.write(Charset.forName("UTF-8").encode("欢迎来到聊天室~"));
    }


    /**
     * 处理可读状态
     * */
    public void readable(Selector selector,SelectionKey selectionKey) throws IOException {

        //从SelectKey获取就绪的通道
        SocketChannel socketChannel= (SocketChannel) selectionKey.channel();

        //创建buffer
        ByteBuffer buffer=ByteBuffer.allocate(1024);

        //循环读取客户端信息
        StringBuilder stringBuilder=new StringBuilder();
        int readLength = socketChannel.read(buffer);
        if (readLength>0){
            //切换读模式
            buffer.flip();
            //读取内容
            stringBuilder.append(Charset.forName("UTF-8").decode(buffer));
        }
        //把通道注册到选择器上
        socketChannel.register(selector,SelectionKey.OP_READ);

        //广播到其他客户端
       if (stringBuilder.length()>0){
           System.out.println(stringBuilder);
           castClient(selector,socketChannel, String.valueOf(stringBuilder));
       }
    }

    /**
     * 广播到其他客户端
     * */
    public  void  castClient(Selector selector,SocketChannel socketChannel,String message) throws IOException {
        // 获取所有已经接入的channel
        Set<SelectionKey> selectionKeySet=selector.keys();

        //循环所有广播消息
        for (SelectionKey selectionKey : selectionKeySet) {
            //获取每个channel
            Channel tarChannel=selectionKey.channel();
            //不需要给自己发送
            if(tarChannel instanceof  SocketChannel&&tarChannel!=socketChannel){
                ((SocketChannel) tarChannel).write(Charset.forName("UTF-8").encode(message));
            }
        }


    }
}

客户端

public class TimClient {
    public static void main(String[] args) throws IOException {
        new TimClient().startClient("ylc");
    }

    public void startClient(String name) throws IOException {
        //连接服务器
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress( 8888));
        //接收服务端响应
        Selector selector = Selector.open();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);

        //创建线程 获取服务器的消息
        new Thread(new ClientThread(selector)).start();
        //向服务器发送消息 控制台输入
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            String msg = scanner.nextLine();
            if (msg.length() > 0) {
                socketChannel.write(Charset.forName("UTF-8").encode(name+":"+msg));
            }
        }
    }


}

实现效果:

image-20220403142936425

标签:SocketChannel,聊天室,NIO,实现,Selector,socketChannel,new,selector,public
来源: https://www.cnblogs.com/cg-ww/p/16153656.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有