NIO多人聊天

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 (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 监听
     */
    public void listen() {
        try {
            while (true) {
                int count = selector.select();
                // count > 0 就表示有事件要处理
                if (count > 0) {
                    // 拿到selectionKey的集合
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
                        // 取出selectionKey
                        SelectionKey key = iterator.next();
                        // 监听到不同的事件进行不同的处理
                        listenHandler(key);
                        // 删除当前key,防止重复处理
                        iterator.remove();
                    }
                } else {
                    System.out.println("当前没事件要处理,等待中……");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    
    /**
     * 针对监听到的不同事件做不同的处理
     * @param key
     * @throws Exception
     */
    public void listenHandler(SelectionKey key) {
        SocketChannel sc = null;
        try {
            // 如果是连接事件
            if (key != null && key.isAcceptable()) {
                // 拿到socketChannel并注册到selector上
                sc = listenChannel.accept();
                sc.configureBlocking(false);
                sc.register(selector, SelectionKey.OP_READ);
                // 提示:xxx上线了
                System.out.println(sc.getRemoteAddress().toString().substring(1) + "上线了");
            }
            // 如果是读取事件
            if (key != null && key.isReadable()) {
                // 拿到socketChannel
                sc = (SocketChannel) key.channel();
                sc.configureBlocking(false);
                // 创建buffer
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                // 将客户端消息读到buffer中去
                int count = sc.read(buffer);
                if (count > 0) {
                    // 如果读取到了数据,就把缓冲区数据转成字符串输出
                    String msg = new String(buffer.array());
                    System.out.println("from client " + msg);
                    // 将该消息转发给其他客户端,
                    sendMsgToClient(msg, sc);
                }
            }
        } catch (IOException e) {
            try {
                System.out.println(sc.getRemoteAddress().toString().substring(1) + "离线了");
                // 取消注册
                key.cancel();
                // 关闭通道
                sc.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
    
    
    /**
     * 发送消息到客户端,要排除当前客户端。
     * 假如A、B、C三个客户端,当前消息是A发来的,那么只转发给B和C就可以。
     * @param msg
     * @param self
     * @throws IOException 
     */
    public void sendMsgToClient(String msg, SocketChannel self) throws IOException {
        System.out.println("服务器转发消息中");
        // 遍历所有注册到selector上的SocketChannel,并排除自己
        for (SelectionKey key : selector.keys()) {
            Channel channel = key.channel();
            if (channel instanceof SocketChannel && channel != self) {
                SocketChannel targetChannel = (SocketChannel) channel;
                // 将msg写到buffer中
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                // 将buffer数据写入通道
                targetChannel.write(buffer);
            }
        }
    }
    
    
    public static void main(String[] args) {
        GroupChatServer server = new GroupChatServer();
        server.listen();
    }
}
public class GroupChatClient {

    // 定义相关属性
    private final String HOST = "127.0.0.1";
    private final int PORT = 6666;
    private Selector selector;
    private SocketChannel socketChannel;
    private String username;

    /**
     * 构造器,进行初始化
     */
    public GroupChatClient() {
        try {
            selector = Selector.open();
            // 连接服务器
            socketChannel = SocketChannel.open(new InetSocketAddress(HOST, PORT));
            // 设置非阻塞
            socketChannel.configureBlocking(false);
            // 将socketChannel注册到selector上
            socketChannel.register(selector, SelectionKey.OP_READ);
            // 拿到username
            username = socketChannel.getLocalAddress().toString().substring(1);
            System.out.println(username + " is ok");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 向服务端发送消息
     * 
     * @param msg
     */
    public void sendMsgToServer(String msg) {
        msg = username + ":" + msg;
        try {
            // 发送消息
            socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 接收服务端发来的消息
     */
    public void acceptMsgFromServer() {
        try {
            int readChannel = selector.select();
            if (readChannel > 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);
                        // 将通道中的数据读到buffer中
                        sc.read(buffer);
                        // 将buffer中的数据转成字符串
                        String msg = new String(buffer.array());
                        System.out.println(msg.trim());
                        // 移除当前的key,防止重复操作
                        iterator.remove();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // 1. 启动客户端
        GroupChatClient client = new GroupChatClient();
        // 2. 启动线程,每隔3秒就读取一次服务端的消息
        new Thread() {
            public void run() {
                while (true) {
                    client.acceptMsgFromServer();
                    try {TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace();} 
                }
            }
        }.start();
        // 3. 发送数据到服务端
        @SuppressWarnings("resource")
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
            String msg = scanner.nextLine();
            client.sendMsgToServer(msg);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值