nio学习实践--简易的群体聊天室

客户端代码(可启动多个):

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.nio.charset.Charset;
import java.util.Random;
import java.util.Scanner;

/**
 * @description:
 * @author:chenbin
 * @Date:2017/4/11
 */
public class SendMessager {

    private Selector selector;

    private int code = new Random().nextInt(1000);

    // 定义实现编码、解码的字符集对象
    private Charset charset = Charset.forName("UTF-8");

    public static void main(String[] args) throws IOException {

        new SendMessager().init();
    }

    public void init() throws IOException {
        //与远程端口建立连接
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(new InetSocketAddress("127.0.0.1",9999));
        //创建选择器,将channel注册到selector
        selector = Selector.open();
        socketChannel.register(selector, SelectionKey.OP_CONNECT);
        //监听selector就绪事件
        new ClientThread().start();
        //创建键盘输入流
        Scanner scan = new Scanner(System.in);
        while (scan.hasNextLine())
        {
            //读取键盘输入
            String line = code + "发出信息:" + scan.nextLine();
            //将键盘输入的内容输出到SocketChannel            socketChannel.write(charset.encode(line));
        }
    }

    //定义读取服务器数据的线程
    private class ClientThread extends Thread
    {
        public void run()
        {
            try
            {
                while (selector.select() > 0)
                {
                    //遍历每个有可用IO操作Channel对应的SelectionKey
                    for (SelectionKey sk : selector.selectedKeys())
                    {
                        //删除正在处理的SelectionKey
                        selector.selectedKeys().remove(sk);
                        if(sk.isConnectable()){
                            SocketChannel sc = (SocketChannel)sk.channel();
                            //如果正在连接,则完成连接
                            if (sc.isConnectionPending()) {
                                sc.finishConnect();
                            }
                            sc.configureBlocking(false);
                            sc.write(ByteBuffer.wrap(new String(code + "上线了").getBytes()));
                            sc.register(selector,SelectionKey.OP_READ);
                        }
                        //如果该SelectionKey对应的Channel中有可读的数据
                        if (sk.isReadable())
                        {
                            //使用NIO读取Channel中的数据
                            SocketChannel sc = (SocketChannel)sk.channel();
                            ByteBuffer buff = ByteBuffer.allocate(1024);
                            String content = "";
                            while(sc.read(buff) > 0)
                            {
                                sc.read(buff);
                                buff.flip();
                                content += charset.decode(buff);
                            }
                            //打印输出读取的内容
                            System.out.println(content);
                            //为下一次读取作准备
                            sk.interestOps(SelectionKey.OP_READ);
                        }
                    }
                }
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
    }
}




服务端代码:

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

/**
 * @description:
 * @author:chenbin
 * @Date:2017/4/11
 */
public class MessageReceriver {

    // 定义实现编码、解码的字符集对象
    private Charset charset = Charset.forName("UTF-8");

    public static void main(String[] args) throws IOException {

        //监听端口,创建socketChannel
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);
        serverChannel.socket().bind(new InetSocketAddress(9999));

        //创建选择器,将channel注册到selector
        Selector selector = Selector.open();
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);

        new MessageReceriver().listen(selector);
    }

    private void listen(Selector selector) throws IOException {
        //获取selector就绪的事件
        while (selector.select() > 0){
            selector.select();

            Iterator<SelectionKey> selectorKeys = selector.selectedKeys().iterator();
            while (selectorKeys.hasNext()){
                SelectionKey key = selectorKeys.next();
                selectorKeys.remove();
                if(key.isAcceptable()){
                    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                    SocketChannel sockerChannel = serverChannel.accept();
                    sockerChannel.configureBlocking(false);
                    sockerChannel.register(selector,SelectionKey.OP_READ);
                }
                if(key.isReadable()){
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    socketChannel.configureBlocking(false);
                    ByteBuffer byteBuffer = ByteBuffer.allocate(48);
                    String content = "";
                    try {
                        while (socketChannel.read(byteBuffer) > 0) {
                            byteBuffer.flip();
                            content += charset.decode(byteBuffer);
                        }
                        System.out.println("=====" + content);
                        key.interestOps(SelectionKey.OP_READ);
                    }catch (Exception e){
                        key.cancel();
                        if(key.channel() != null){
                            key.channel().close();
                        }
                    }
                    // 如果content的长度大于0,即聊天信息不为空
                    if (content.length() > 0) {
                        // 遍历该selector里注册的所有SelectKey
                        for (SelectionKey key1 : selector.keys()) {
                            // 获取该key对应的Channel
                            Channel targetChannel = key1.channel();
                            // 如果该channelSocketChannel对象
                            if (targetChannel instanceof SocketChannel) {
                                // 将读到的内容写入该Channel                                SocketChannel dest = (SocketChannel) targetChannel;
                                dest.write(charset.encode(content));
                            }
                        }
                    }
                }
            }
        }



        //对事件进行处理
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值