5 Java NIO群聊系统Demo

Java NIO群聊系统Demo
使用的是NIO三大组件,前面介绍的知识。

服务端编写
(1)服务器启动并接听6667
(2)监听上线和下线
(3)接收客户端消息,并实现转发

package NIO.chat;

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

public class Server {
    //定义属性
    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private static final int PORT = 6667;

    //构造器
    public Server(){
        try {
            //获取选择器和服务器端channel
            selector = Selector.open();
            serverSocketChannel = ServerSocketChannel.open();
            //绑定端口
            serverSocketChannel.bind(new InetSocketAddress(PORT));
            //设置非阻塞模式
            serverSocketChannel.configureBlocking(false);
            //将channel注册到selector中
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //监听程序
    public void listen(){
        try {
            while(true){
                int count = selector.select();
                if (count>0) {
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();
                    while (iterator.hasNext()){
                        SelectionKey key = iterator.next();
                        //监听到连接事件
                        if (key.isAcceptable()){
                            SocketChannel accept = serverSocketChannel.accept();
                            accept.configureBlocking(false);
                            //将该channel注册到选择器中,监听可读事件
                            accept.register(selector,SelectionKey.OP_READ);
                            System.out.println(accept.getRemoteAddress()+" 上线了");
                        }
                        //监听到通道可读
                        if (key.isReadable()) {
                            //处理读
                            readData(key);
                        }

                        //删除key,防止重复操作
                        iterator.remove();
                    }


                } else {
                    System.out.println("等待连接。。。");
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //读取客户端消息
    public void readData(SelectionKey key){
        SocketChannel channel = null;
        try {
            channel = (SocketChannel) key.channel();
            //创建buffer
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int count = channel.read(buffer);
            if(count>0){
                //把缓冲区的数据转换成字符串
                String msg = new String(buffer.array());
                System.out.println("from 客户端"+ channel.getRemoteAddress() + ":"+ msg);
                //向其他客户端转发消息,排除自己。
                sendMSGToOtherClient(msg,channel);
            }
        } catch (IOException e) {
            try {
                System.out.println(channel.getRemoteAddress() + "下线了");
                //取消注册
                key.cancel();
                //关闭通道
                channel.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }


    }

    public void sendMSGToOtherClient(String msg, SocketChannel self) throws IOException {
        //遍历所有注册到selector上的channel。
        for (SelectionKey key : selector.keys()){
            Channel target = key.channel();
            if (target instanceof SocketChannel && target != self){
                SocketChannel socketChannel = (SocketChannel) target;
                //转发信息
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                socketChannel.write(buffer);
            }
        }
    }

    public static void main(String[] args) {
        //创建服务器端对象
        Server server = new Server();
        server.listen();

    }
}

客户端编写
(1)连接服务器
(2)发送消息
(3)接受消息

package NIO.chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

public class Client {
    //服务器相关信息
    private final String HOST = "127.0.0.1";
    private final int PORT = 6667;
    private Selector selector;
    private SocketChannel socketChannel;
    private String username;


    public Client() throws IOException {
        selector = Selector.open();
        socketChannel = SocketChannel.open(new InetSocketAddress(HOST,PORT));
        //设置非阻塞
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
        //得到username
        username = socketChannel.getLocalAddress().toString();
        System.out.println(username + "is ok");

    }

    //向服务器发送消息
    public void sendMSG(String msg) throws IOException {
        msg = username + " 说:" + msg;
        socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
    }

    //读取服务端消息
    public void readMSG() throws IOException {
        int readChannels = selector.select();
        if(readChannels>0){
            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();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    channel.read(buffer);
                    String msg = new String(buffer.array());
                    System.out.println(msg);
                }

                //删除key,防止重复操作
                iterator.remove();
            }

        } else {
            System.out.println("没有可用通道");
        }

    }

    public static void main(String[] args) throws IOException {
        //启动客户端
        Client client = new Client();
        //启动一个线程监听服务端发送的数据
        new Thread(){
            public void run(){
                while (true){
                    try {
                        client.readMSG();
                        //每隔3秒从服务器端读取数据
                        Thread.currentThread().sleep(3000);
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }

        }.start();

        //发送数据
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()){
            String s = scanner.nextLine();
            client.sendMSG(s);

        }
    }
}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值