Loading

基于NIO的简单群聊

直接贴代码

服务器端

package GroupChat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class GroupServer {

    private Selector selector;
    private ServerSocketChannel listen;
    private static final int PORT = 6667;

    public GroupServer() {
        try {
            //得到选择器
            selector = Selector.open();
            //得到ServerSocketChannel
            listen = ServerSocketChannel.open();
            //绑定端口
            listen.socket().bind(new InetSocketAddress(PORT));
            //设置非阻塞
            listen.configureBlocking(false);
            //将ServerSocketChannel注册到Selector
            listen.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //监听
    public void listen() {
        try {
            while (true) {
                int count = selector.select(2000);
                if (count > 0) {//有事件处理
                    //遍历得到selectionkey集合
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
                        //取出selectionkey
                        SelectionKey key = iterator.next();
                        //监听accept
                        if (key.isAcceptable()) {
                            SocketChannel socketChannel = listen.accept();
                            //注册到selector上
                            socketChannel.configureBlocking(false);
                            socketChannel.register(selector, SelectionKey.OP_READ);
                            //提示
                            System.out.println(socketChannel.getRemoteAddress() + "  上线");
                        } else if (key.isReadable()) {//通道发生read事件,即通道是可读事件
                            readData(key);
                        }
                        //删除当前的key
                        iterator.remove();
                    }
                } else {
                    System.out.println("等待");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
    }

    //读取客户端消息
    private void readData(SelectionKey key) throws IOException {
        //定义一个SocketChannel
        SocketChannel socketChannel = null;
        try {
            //取得关联的Channel
            socketChannel = (SocketChannel) key.channel();
            //创建缓冲
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            int count = socketChannel.read(byteBuffer);
            if (count > 0) {
                //把缓冲区转换成字符串
                String msg = new String(byteBuffer.array());
                //输出该消息
                System.out.println("from 客户端: " + msg);
                //向其他的客户端转发消息(去掉自己)
                forwardMsg(msg, socketChannel);
            }

        } catch (IOException e) {
            System.out.println(socketChannel.getRemoteAddress() + " 离线了");
            //取消注册
            key.cancel();
            //关闭通道
            socketChannel.close();
            e.printStackTrace();
        }
    }

    //转发其他的消息
    private void forwardMsg(String message, SocketChannel self) throws IOException {
        System.out.println("服务器转发消息");
        //遍历注册到selector上的SocketChannel并排除自己
        for (SelectionKey key : selector.keys()) {
            //通过对应的key取出对应的Channel
            Channel targetChannel = key.channel();
            //排除自己
            if (targetChannel instanceof SocketChannel && targetChannel != self) {
                //转型
                SocketChannel dest = (SocketChannel) targetChannel;
                //将msg存储到Buffer
                ByteBuffer byteBuffer = ByteBuffer.wrap(message.getBytes());
                //将Buffer的数据写入通道
                dest.write(byteBuffer);
            }
        }
    }


    public static void main(String[] args) {
        GroupServer groupServer = new GroupServer();
        groupServer.listen();
    }
}

客户端

package GroupChat;

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;

public class GroupClient {
    public static final String HOST = "127.0.0.1";
    public static final int PORT = 6667;
    private Selector selector;
    private SocketChannel socketChannel;
    private String username;

    public GroupClient() {
        try {
            selector = Selector.open();
            //连接服务器
            socketChannel = SocketChannel.open(new InetSocketAddress(HOST, PORT));
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ);
            username = socketChannel.getLocalAddress().toString().substring(1);
            System.out.println(username + " is OK");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //向服务器发送消息
    public void sendMsg(String info) {
        info = username + "说:" + info;
        try {
            socketChannel.write(ByteBuffer.wrap(info.getBytes()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //读取服务器消息
    public void readMsg() {
        try {
            int readChannels = selector.select();
            if (readChannels > 0) {
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    if (key.isReadable()) {
                        //得到相关通道
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        //得到一个Buffer
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        //读取
                        socketChannel.read(byteBuffer);
                        String msg = new String(byteBuffer.array()).trim();
                        System.out.println(msg);
                    }
                }
                iterator.remove();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //启动客户端
        GroupClient groupClient = new GroupClient();
        //启动一个线程
        new Thread(() -> {
            while (true) {
                groupClient.readMsg();
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        //发送数据
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
            String s = scanner.nextLine();
            groupClient.sendMsg(s);
        }
    }
}
posted @ 2021-05-30 14:58  Xianhao  阅读(47)  评论(0编辑  收藏  举报