NIO练习----群聊系统

NIO的三个核心组件为Selector,Channel,Buffer,下面基于NIO来完成一个群聊系统

服务端:

package com.jym.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;

/**
 * @program: JymNetty
 * @description: 服务端
 * @author: jym
 * @create: 2020/02/02
 */
public class GroupChatServer {

    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private final int PORT=6667;

    /**
     * 通过构造方法来初始化各个参数
     */
    public GroupChatServer() {
        try {
            selector = Selector.open();
            serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
            serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @description:主要监听方法
     */
    public void listen(){
        try {
            while (true){
                int select = selector.select();
                if(select>0){
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();
                    while (iterator.hasNext()){
                        SelectionKey selectionKey = iterator.next();
                        if(selectionKey.isAcceptable()){
                            SocketChannel socketChannel = serverSocketChannel.accept();
                            socketChannel.configureBlocking(false);
                            socketChannel.register(selector,SelectionKey.OP_READ);
                            System.out.println(socketChannel.getRemoteAddress()+"上线了");
                        }
                        if(selectionKey.isReadable()){
                            readData(selectionKey);
                        }
                        iterator.remove();
                    }
                }else {
                    System.out.println("系统正在等待人上线....");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }

    /**
     * @description:读取客户端发送的消息,并向其他客户端转发消息
     * @param selectionKey
     */
    private void readData(SelectionKey selectionKey){
        SocketChannel socketChannel = null;
        try {
            socketChannel = (SocketChannel)selectionKey.channel();
            socketChannel.configureBlocking(false);
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            int read = socketChannel.read(byteBuffer);
            if(read>0){
                String msg = new String(byteBuffer.array());
                System.out.println("from客户端"+msg);
                // 向其他客户端转发消息
                sendInfoToOtherClient(msg,socketChannel);
            }
        } catch (IOException e) {
            try {
                System.out.println(socketChannel.getRemoteAddress()+"离线了");
                // 取消注册
                selectionKey.cancel();
                socketChannel.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

    }

    /**
     * @description: 向其他客户端转发消息
     * @param msg
     * @param socketChannel
     */
    private void sendInfoToOtherClient(String msg, SocketChannel socketChannel){
        System.out.println("服务器转发消息中");
        // 遍历所有注册到selector的所有channel,排除自己
        for (SelectionKey selectionKey : selector.keys()) {
            Channel taGetChannel = selectionKey.channel();
            if(taGetChannel instanceof SocketChannel && taGetChannel!=socketChannel){
                SocketChannel socketChannel1 = (SocketChannel)taGetChannel;
                ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
                try {
                    socketChannel1.write(byteBuffer);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

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

}

服务端:

package com.jym.nio.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;

/**
 * @program: JymNetty
 * @description: 客户端
 * @author: jym
 * @create: 2020/02/02
 */
public class GroupChatClient {

    private final String HOST = "127.0.0.1";
    private final int PORT = 6667;
    private Selector selector;
    private SocketChannel socketChannel;
    private String username;

    public GroupChatClient() throws IOException {
        selector = Selector.open();
        // 连接服务器
        socketChannel = SocketChannel.open(new InetSocketAddress(HOST, PORT));
        this.socketChannel.configureBlocking(false);
        this.socketChannel.register(selector, SelectionKey.OP_READ);
        username = this.socketChannel.getRemoteAddress().toString().substring(1);
        System.out.println(username+"isOK");
    }

    /**
     * @description: 发送消息
     * @param info
     */
    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 read = selector.select();
            if(read>0){
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()){
                    SelectionKey selectionKey = iterator.next();
                    if(selectionKey.isReadable()){
                        SocketChannel channel = (SocketChannel)selectionKey.channel();
                        channel.configureBlocking(false);
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        int read1 = channel.read(byteBuffer);
                        if(read1>0){
                            System.out.println(new String(byteBuffer.array()).trim());
                        }
                    }
                    iterator.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws IOException {
        // 启动客户端
        GroupChatClient groupChatClient = new GroupChatClient();

        // 启动一个线程,没隔三秒,读取发送的数据
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    groupChatClient.readInfo();
                    try {
                        Thread.currentThread().sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        // 发送数据
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            String s = scanner.nextLine();
            groupChatClient.sendInfo(s);
        }

    }
}

我们用idea 启动·两个客户端一个服务端:
结果:
服务端
在这里插入图片描述
客户端1:
在这里插入图片描述
客户端2:
在这里插入图片描述
这里说一下idea启动两个mian的方法:
在这里插入图片描述
点击加号,选择application
在这里插入图片描述
输入class名称然后确定
在这里插入图片描述
然后选择我们新建的application,点击运行按钮即可
在这里插入图片描述

学习年限不足,知识过浅,说的不对请见谅。

世界上有10种人,一种是懂二进制的,一种是不懂二进制的。

发布了71 篇原创文章 · 获赞 54 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/weixin_43326401/article/details/104152612