JavaNIO简单聊天室,服务端+客户端(源码)

package com.ct;

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

/***************************
 *Author:ct
 *Time:2020/5/6 18:11
 *Dec:Java NIO 练习 聊天室 服务端
 * Buffer 跟channel进行交互,数据的介质
 *      -- ByteBuffer
 *      -- 其他基本类型buffer
 *      优点: 灵活 配合channel可以读和写 stream只有读或写
 *      直接缓冲区allocateDirect()、非直接缓冲allocate()
 *      属性: capacity, position, mark, limit
 *      方法: put(), get, flip, clear, compact, rewind, mark, reset
 * Channel 数据运输的通道 阻塞或非阻塞
 *      -- FileChannel
 *      -- SocketChannel
 *      -- ServerSocketChannel
 *      -- DatagramChannel
 *      方法: read(), write(), configureBlock()
 * selector 通过选择器实现多路复用,选择器管理多个channel
 * pipe 共享的pipe传输数据
 ****************************/
public class Server {

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

        //获得serverSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //绑定端口
        serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 8888));
        //buffer
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //Selector, 多路复用 ,用来管理所有的channel
        Selector selector = Selector.open();
        //设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        //将serverSocketChannel的accept事件注册进来
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务端以启动》》》》》》》");

        while (selector.select() > 0) {//不能用while(true) select()阻塞在这里
            //所有事件准备好的channel
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            //取出所有 有事件的channel
            while (iterator.hasNext()) {

                SocketChannel channel;
                SelectionKey key = iterator.next();
                //读
                if (key.isReadable()) {
                    channel = (SocketChannel) key.channel();
                    //读取内容
                    int len;
                    StringBuilder sb = new StringBuilder();
                    while ((len = channel.read(buffer)) > 0) {
                        buffer.flip();
                        sb.append(new String(buffer.array(), 0, len));
                        buffer.clear();
                    }
                    if (len == -1) {//-1代表客户端断开连接
                        //客户端断开连接
                        System.out.println(channel.getRemoteAddress() + "断开连接....");
//                        channel.close();//关闭当前通道,或者key.cancel()
                        key.cancel();
                    }
                    System.out.println(sb.toString());
                }
                //写
                else if (key.isWritable()) {
                }
                //SocketChannel 连接就绪
                else if (key.isConnectable()) {
                }
                //ServerSocketChannel接收连接
                else if (key.isAcceptable()) {
                    SocketChannel newChannel = ((ServerSocketChannel) (key.channel())).accept();
                    System.out.println(newChannel.getRemoteAddress() + "建立连接.....");
                    //设置channel为非阻塞
                    newChannel.configureBlocking(false);
                    //将 读 事件 注册到selector中
                    newChannel.register(selector, SelectionKey.OP_READ);
                }
                //移除当前事件
                iterator.remove();
            }
        }
        serverSocketChannel.close();
        selector.close();
    }
}

package com.ct;

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

/***************************
 *Author:ct
 *Time:2020/5/6 18:44
 *Dec:Java NIO 练习 聊天室 客户端
 ****************************/
public class Client {

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

        SocketChannel socketChannel = SocketChannel.open();
//        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8888));
        //设置连接的服务器
        socketChannel.connect(new InetSocketAddress("127.0.0.1", 8888));
        //buffer
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        Scanner sc = new Scanner(System.in);
        System.out.println("客户端以启动》》》》》》》");
        while (sc.hasNext()) {

            //发送消息
            String word = sc.nextLine();
            buffer.put(word.getBytes());
            buffer.flip();
            socketChannel.write(buffer);
            buffer.clear();

            if(word.equals("bye")) break;
        }
        socketChannel.close();
    }
}

你可能感兴趣的:(Java)