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

Posted hyy9527

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于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();
}
}

以上是关于基于NIO实现后台简易群聊系统的主要内容,如果未能解决你的问题,请参考以下文章

使用Nio实现一个简易的群聊和单聊

4.基于NIO的群聊系统

基于Java NIO的多人在线聊天工具源码实现(登录,单聊,群聊)

简易版聊天系统实现 Socket VS NIO两种实现方式

nio 代码实现简易多人聊天

简易版聊天系统实现 Socket VS NIO两种实现方式