NIO实现一个群聊系统

NIO我一生之敌

Server

package io;

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 ServerNIO {
    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        InetSocketAddress serverAddress = new InetSocketAddress(8080);
        serverChannel.bind(serverAddress);
        serverChannel.configureBlocking(false);
        Selector selector = Selector.open();
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("【log】服务器启动成功");

        while(true) {
            selector.select();
            Set<SelectionKey> selectionKey = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKey.iterator();
            while(iterator.hasNext()) {
                SelectionKey key = iterator.next();
                if(key.isAcceptable()) {
                    //连接事件
                    acceptHandle(serverChannel, selector);
                } else if(key.isReadable()) {
                    //读事件
                    readHandle(serverChannel, selector, key);
                }
                iterator.remove();
            }
        }

    }

    public static void acceptHandle(ServerSocketChannel serverChannel, Selector selector) throws IOException {
        SocketChannel socketChannel = serverChannel.accept();
        socketChannel.configureBlocking(false);
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //让每个事件携带一个buffer,以后就不用了allocate啦
        socketChannel.register(selector, SelectionKey.OP_READ, buffer);
        System.out.println("【log】" + socketChannel.getRemoteAddress() + "建立连接");

        //给socketChannel发送消息:欢迎来到群聊系统
        sendToSelf("欢迎来到XXX交流群", socketChannel, buffer);

        //给其余socketChannel发送消息:xxx加入群聊系统
        sendToOther("初次见面大家多多关照", selector, serverChannel, socketChannel);
    }

    public static void readHandle(ServerSocketChannel serverChannel, Selector selector, SelectionKey key) throws IOException {
        SocketChannel socketChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = (ByteBuffer) key.attachment();
        buffer.clear();

        try {
            //将buffer中的消息读取出来发送给其余人
            int f = socketChannel.read(buffer);
            while (f > 0) {
                buffer.flip();
                String msg = new String(buffer.array(), 0, f);
                System.out.println("【log】" + socketChannel.getRemoteAddress() + "发送消息:" + msg);
                sendToOther(msg, selector, serverChannel, socketChannel);
                buffer.clear();
                f = socketChannel.read(buffer);
            }
        } catch (IOException e){
            //当一个通道关闭时会触发该通道的读事件
            System.out.println("【log】" + socketChannel.getRemoteAddress() + "用户下线了");
            sendToOther("你们先聊,我溜了", selector, serverChannel, socketChannel);
            key.cancel();
            socketChannel.close();
        }
    }

    public static void sendToOther(String msg, Selector selector, ServerSocketChannel server, SocketChannel self) throws IOException {
        Set<SelectionKey> selectionKeys = selector.keys();
        for(SelectionKey selectionKey : selectionKeys) {
            Channel channel = selectionKey.channel();
            if(server == channel) continue;
            if(self == channel) continue;

            ByteBuffer buffer = (ByteBuffer) selectionKey.attachment();
            sendToSelf(self.getRemoteAddress() + ": " + msg, (SocketChannel) channel, buffer);
        }
    }

    public static void sendToSelf(String msg, SocketChannel socketChannel, ByteBuffer buffer) throws IOException {
        buffer.clear();
        buffer.put(msg.getBytes());
        buffer.flip();
        socketChannel.write(buffer);
    }

}

Client

package io;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;

public class ClientNIO {
    public static void main(String[] args) throws IOException, InterruptedException {
        SocketChannel channel = SocketChannel.open();
        SocketAddress address = new InetSocketAddress("localhost", 8080);
        channel.connect(address);

        new Thread(() -> {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            Scanner scanner = new Scanner(System.in);
            while(true) {
                String msg = scanner.nextLine();
                buffer.put(msg.getBytes());
                buffer.flip();
                try {
                    channel.write(buffer);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                buffer.clear();
            }
        }).start();

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while(true) {
            int f = channel.read(buffer);
            buffer.flip();
            while(f > 0) {
                String msg = new String(buffer.array(), 0, f);
                buffer.clear();
                System.out.println(msg);
                f = channel.read(buffer);
            }

        }


    }

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值