• 基于NIO实现后台简易群聊系统


    1.服务端

    public class GroupChatServer {
        private Selector selector;
        private ServerSocketChannel listenChannel;
        private static final int PORT = 6677;
    
        //初始化工作
        public GroupChatServer() {
            try {
                selector = Selector.open();
                listenChannel = ServerSocketChannel.open();
                //绑定端口
                listenChannel.socket().bind(new InetSocketAddress(PORT));
                //设置非阻塞
                listenChannel.configureBlocking(false);
                //注册
                listenChannel.register(selector, SelectionKey.OP_ACCEPT);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        //监听
        public void listen() {
            try {
                while (true) {
                    int count = selector.select(2000);
                    if (count > 0) {
                        //遍历得到SelectionKey的集合
                        Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                        //获取key
                        SelectionKey key = iterator.next();
                        //监听accept
                        if (key.isAcceptable()) {
                            SocketChannel socketChannel = listenChannel.accept();
                            socketChannel.configureBlocking(false);
                            //将socketChannel注册到selector
                            socketChannel.register(selector, SelectionKey.OP_READ);
                            //提示上线
                            System.out.println(socketChannel.getRemoteAddress().toString().substring(1) + "上线了");
                        }
                        if (key.isReadable()) {//通道为可读状态
                            //读取数据
                            readData(key);
                        }
                        //删除当前key,防止重复处理
                        iterator.remove();
                    }
    
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
        //读取客户发送的消息
        public void readData(SelectionKey key) {
            //定义一个SocketChannel
            SocketChannel channel = null;
            try {
                //得到channel
                channel = (SocketChannel) key.channel();
                //创建buffer
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                int read = channel.read(byteBuffer);
                if (read > 0) {
                    //缓存区的数据转存到字符串
                    String msg = new String(byteBuffer.array());
                    //输出
                    System.out.println("来自客户端的消息" + msg);
    
                    //服务器接收到某个客户的消息后,转发给其他客户
                    sendToOthers(msg, channel);
    
                }
            } catch (IOException e) {//此时表示客户离线了
                try {
                    System.out.println(channel.getRemoteAddress() + "离线了....");
                    //取消注册
                    key.cancel();
                    //关闭通道
                    channel.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }
        }
        //消息转发给其他用户
        private void sendToOthers(String msg, SocketChannel self) throws IOException {
            System.out.println("服务器消息转发中...");
            //遍历已经注册到selector的socketchannel,排除自己在外
            for (SelectionKey key : selector.keys()) {
                //通过key取出对应的socketChannel
                Channel channel = key.channel();
                //排除自己的channel
                if (channel instanceof SocketChannel & channel != self) {
                    //转型
                    SocketChannel dest = (SocketChannel) channel;
                    //将msg转存到buffer
                    ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
                    //将buffer数据写入到通道
                    dest.write(byteBuffer);
                }
            }
        }
        //服务器启动
        public static void main(String[] args) {
            GroupChatServer groupChatServer = new GroupChatServer();
            groupChatServer.listen();
        }
    }

    2.客户端

    public class GroupChatClient {
        private SocketChannel socketChannel = null;
        private Selector selector = null;
        private final static int PORT = 6677;
        private final static String HOST = "127.0.0.1";
        private String userName;
    
        //初始化
        public GroupChatClient() throws IOException {
            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....");
        }
    
        //向服务器发送消息
        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 select = selector.select();
                if (select > 0) {//判断是否有可用的通道
                    //获取key集合
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    //迭代
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();
                    while (iterator.hasNext()) {
                        SelectionKey key = iterator.next();
                        if (key.isReadable()) {
                            //得到相关通道
                            SocketChannel channel = (SocketChannel) key.channel();
                            //得到一个buffer
                            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                            //读取
                            channel.read(byteBuffer);
                            //数据转为字符串
                            String s = new String(byteBuffer.array());
                            System.out.println(s.trim());
                        }
                    }
                    iterator.remove();
                } else {
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
        public static void main(String[] args) throws IOException {
            GroupChatClient chatClient = new GroupChatClient();
            //读取数据
            new Thread() {
                public void run() {
                    while (true) {
                        chatClient.readInfo();
                    }
                }
            }.start();
            //发送数据
            Scanner sc = new Scanner(System.in);
            while (sc.hasNextLine()) {
                String s = sc.nextLine();
                chatClient.sendInfo(s);
            }
        }
    }
    public class GroupChatServer {
    private Selector selector;
    private ServerSocketChannel listenChannel;
    private static final int PORT = 6677;

    //初始化工作
    public GroupChatServer() {
    try {
    selector = Selector.open();
    listenChannel = ServerSocketChannel.open();
    //绑定端口
    listenChannel.socket().bind(new InetSocketAddress(PORT));
    //设置非阻塞
    listenChannel.configureBlocking(false);
    //注册
    listenChannel.register(selector, SelectionKey.OP_ACCEPT);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    //监听
    public void listen() {
    try {
    while (true) {
    int count = selector.select(2000);
    if (count > 0) {
    //遍历得到SelectionKey的集合
    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
    //获取key
    SelectionKey key = iterator.next();
    //监听accept
    if (key.isAcceptable()) {
    SocketChannel socketChannel = listenChannel.accept();
    socketChannel.configureBlocking(false);
    //将socketChannel注册到selector
    socketChannel.register(selector, SelectionKey.OP_READ);
    //提示上线
    System.out.println(socketChannel.getRemoteAddress().toString().substring(1) + "上线了");
    }
    if (key.isReadable()) {//通道为可读状态
    //读取数据
    readData(key);
    }
    //删除当前key,防止重复处理
    iterator.remove();
    }

    }
    } catch (Exception ex) {
    ex.printStackTrace();
    }
    }

    //读取客户发送的消息
    public void readData(SelectionKey key) {
    //定义一个SocketChannel
    SocketChannel channel = null;
    try {
    //得到channel
    channel = (SocketChannel) key.channel();
    //创建buffer
    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    int read = channel.read(byteBuffer);
    if (read > 0) {
    //缓存区的数据转存到字符串
    String msg = new String(byteBuffer.array());
    //输出
    System.out.println("来自客户端的消息" + msg);

    //服务器接收到某个客户的消息后,转发给其他客户
    sendToOthers(msg, channel);

    }
    } catch (IOException e) {//此时表示客户离线了
    try {
    System.out.println(channel.getRemoteAddress() + "离线了....");
    //取消注册
    key.cancel();
    //关闭通道
    channel.close();
    } catch (IOException e1) {
    e1.printStackTrace();
    }
    e.printStackTrace();
    }
    }
    //消息转发给其他用户
    private void sendToOthers(String msg, SocketChannel self) throws IOException {
    System.out.println("服务器消息转发中...");
    //遍历已经注册到selector的socketchannel,排除自己在外
    for (SelectionKey key : selector.keys()) {
    //通过key取出对应的socketChannel
    Channel channel = key.channel();
    //排除自己的channel
    if (channel instanceof SocketChannel & channel != self) {
    //转型
    SocketChannel dest = (SocketChannel) channel;
    //将msg转存到buffer
    ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
    //将buffer数据写入到通道
    dest.write(byteBuffer);
    }
    }
    }
    //服务器启动
    public static void main(String[] args) {
    GroupChatServer groupChatServer = new GroupChatServer();
    groupChatServer.listen();
    }
    }
  • 相关阅读:
    .NET 2.0 WinForm Control DataGridView 编程36计(一)
    Sql Server 日期格式化函数
    FastReport 金额大小写转换自定义函数
    vue.js 三种方式安装(vuecli)
    Android style
    android ui 布局性能优化
    android 手机分辨率
    TCP,IP,HTTP,SOCKET区别和联系
    android2.2 特性
    常见开放api平台OpenAPI
  • 原文地址:https://www.cnblogs.com/hyy9527/p/13059248.html
Copyright © 2020-2023  润新知