zoukankan      html  css  js  c++  java
  • Netty学习笔记四:NIO实现群聊

    群聊服务端代码

    package com.mytest.netty.nio.groupChat;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.*;
    import java.util.Iterator;
    import java.util.Set;
    
    public class GroupChatServer {
    
        //定义相关属性
        private Selector selector;
        private ServerSocketChannel listenChannel;
        private static final int PORT = 6666;
    
        //初始化工作
        public GroupChatServer() {
            try{
                //得到选择器
                selector = Selector.open();
                //得到ServerSocketChannel
                listenChannel = ServerSocketChannel.open();
                //绑定端口
                listenChannel.socket().bind(new InetSocketAddress(PORT));
                //设置非阻塞模式
                listenChannel.configureBlocking(false);
                //将listenChannel注册到selector上
                listenChannel.register(selector, SelectionKey.OP_ACCEPT);
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        //监听的代码
        public void listen(){
            try{
                while (true) {
    
                    int count = selector.select();
                    if (count > 0) {//有事件处理
                        Set<SelectionKey> selectionKeys = selector.selectedKeys();
                        Iterator<SelectionKey> iterator = selectionKeys.iterator();
                        while (iterator.hasNext()) {
                            //取出selectionKey
                            SelectionKey key = iterator.next();
    
                            //监听到accpet
                            if (key.isAcceptable()) {
                                SocketChannel sc = listenChannel.accept();
    
                                //设置非阻塞
                                sc.configureBlocking(false);
    
                                //将该sc注册到selector
                                sc.register(selector, SelectionKey.OP_READ);
                                //给出上线提示
                                System.out.println(sc.getRemoteAddress() + "上线 ");
                            }
    
                            if (key.isReadable()) {//通道发生read事件
                                //处理读事件
                                readData(key);
                            }
    
                            //删除当前key,防止重复处理
                            iterator.remove();
                        }
                    } else {//等待
                        System.out.println("等待中。。。。。");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
    
            }
        }
    
        //读取客户端消息
        private void readData(SelectionKey key) {
            //定义一个socketChannel
            SocketChannel channel = null;
            try{
                //得到channel
                channel = (SocketChannel) key.channel();
                //创建Buffer
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                int count = channel.read(buffer);
    
                //根据count的值做处理
                if (count > 0) {
                    //将缓冲区的数据转为字符串并输出
                    String msg = new String(buffer.array());
                    //输出该消息
                    System.out.println(channel.getRemoteAddress() + "" + msg);
    
                    //向其他客户端转发消息(去掉自己)
                    sendInfoToOtherClients(msg, channel);
                }
    
            } catch (IOException e) {
                try{
                    //处理发送过程中断开链接的情况
                    System.out.println(channel.getRemoteAddress() + "已离线。。。");
                    //取消注册
                    key.cancel();
                    //关闭通道
                    channel.close();
                }catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    
        //转发消息给其他客户(通道)
        private void sendInfoToOtherClients(String msg, SocketChannel self) throws IOException{
    
            System.out.println("服务器消息发送中。。。");
            for (SelectionKey key : selector.keys()) {
                //通过key, 去除对应的SocketChannel
                Channel targetChannel = key.channel();  //使用Channel也可以接受,因为SocketChannel实现了Channel
    
                //排除自己的Channel
                if (targetChannel instanceof SocketChannel && !self.equals(targetChannel)) {
                    SocketChannel dest = (SocketChannel) targetChannel;
                    //将msg 存储到Buffer
                    ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                    //将buffer的数据写入到通道中
                    dest.write(buffer);
                }
            }
        }
    
        public static void main(String[] args) {
    
            //创建一个服务器对象
            GroupChatServer chatServer = new GroupChatServer();
    
            //监听
            chatServer.listen();
        }
    }

    客户端代码

    package com.mytest.netty.nio.groupChat;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SelectableChannel;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.SocketChannel;
    import java.util.Iterator;
    import java.util.Scanner;
    
    public class GroupChatClient {
    
        //定义相关属性
        private final String HOST = "127.0.0.1";
        private static final int PORT = 6666;
        private Selector selector;
        private SocketChannel socketChannel;
        private String userName;
    
        //构造器
        public GroupChatClient() throws IOException {
            selector = Selector.open();
            //链接服务器
            socketChannel = socketChannel.open(new InetSocketAddress(HOST, PORT));
    
            //设置非阻塞
            socketChannel.configureBlocking(false);
    
            //将channel注册到selector
            socketChannel.register(selector, SelectionKey.OP_READ);
    
            //得到userName
            userName = socketChannel.getLocalAddress().toString().substring(1);
            System.out.println(userName + "is ok ....");
        }
    
        //向服务器发送消息
        public void sendInfo(String info){
            info = userName + "说:" + info;
    
            try{
                socketChannel.write(ByteBuffer.wrap(info.getBytes()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        //读取从服务端回复的数据
        public void readInfo() {
            try {
                int readChannels = selector.select(2000);
                if (readChannels > 0) {//有可以使用的通道
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
    
                        SelectionKey key = iterator.next();
                        if (key.isReadable()) {
                            //得到相关的通道
                            SocketChannel sc = (SocketChannel) key.channel();
    
                            //得到一个Buffer
                            ByteBuffer buffer = ByteBuffer.allocate(1024);
                            //读取
                            sc.read(buffer);
                            System.out.println(new String(buffer.array()));
                        }
                    }
                    iterator.remove();
                }else {
    //                System.out.println("没有可用的通道");
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws IOException {
    
            //启动客户端
            GroupChatClient chatClient = new GroupChatClient();
    
            //启动一个线程,每隔3S读取从服务器端发送的数据
            new Thread() {
                public void run() {
    
                    while (true) {
                        chatClient.readInfo();
                        try {
                            Thread.currentThread().sleep(3000);
                        }catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
    
            //客户端发送数据给服务端
            Scanner scanner = new Scanner(System.in);
    
            while (scanner.hasNextLine()) {
                String s = scanner.nextLine();
                chatClient.sendInfo(s);
            }
        }
    }
  • 相关阅读:
    SQL Server 深入解析索引存储(非聚集索引)
    class.forName的官方使用方法说明
    使用C++实现学生管理系统
    hdu5033 Building 单调队列
    leetCode 72.Edit Distance (编辑距离) 解题思路和方法
    IOS7 textkit 的相关
    nodejs即时聊天
    5种语言混合编程:C++、JS、python、Lisp、汇编
    java Semaphore信号亮-同意多个任务同一时候訪问这个资源--thinking in java21.7.6
    关于Android的.so文件所须要知道的
  • 原文地址:https://www.cnblogs.com/the-zym/p/14673163.html
Copyright © 2011-2022 走看看