NIO消息转发

该文章是一个关于使用JavaNIO进行网络编程的示例,主要涉及NIOServer如何通过Selector监听和接受SocketChannel连接,以及读取和转发客户端数据。客户端则展示如何建立连接、发送及接收信息。
摘要由CSDN通过智能技术生成
  1. NIO学习笔记
  2. 关于 selector , ServerSocketChannel 网络编程的使用

编写服务端

package src.com.NIO.groupchart;

import javax.xml.soap.SOAPElementFactory;
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 NioServer {

    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private final int port = 6666;

    /**
     * 初始化 server
     * @throws IOException
     */
    public NioServer() throws IOException {
        selector = Selector.open();
        serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(port));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector , SelectionKey.OP_ACCEPT);
    }

    /**
     * 创建 服务端
     */
    public void listen() {
        System.out.println("监听线程 : " + Thread.currentThread().getName());
        try{
            // 循环处理连接请求
            while (true) {
                int count = selector.select();
                if (count > 0 ) {
                    // 获取连接 的 selector 集合
                    Iterator<SelectionKey> selectKeys = selector.selectedKeys().iterator();
                    while (selectKeys.hasNext()) {
                        SelectionKey key = selectKeys.next();
                        // 监听连接请求
                        if (key.isAcceptable()) {
                            SocketChannel socketChannel = serverSocketChannel.accept();
                            socketChannel.configureBlocking(false);
                            socketChannel.register(selector , SelectionKey.OP_READ);
                            // 提示
                            System.out.println(socketChannel.getRemoteAddress() + ": 上线");
                        }
                        if (key.isReadable()) {
                            // 处理读请求
                            readData(key);
                        }
                        selectKeys.remove();
                    }
                }

            }
        }catch (Exception e) {

        }

    }

    /**
     * 读取数据请求的数据
     * @param key
     */
    private void readData(SelectionKey key) {
        // 读取到关联的socketChannel
        SocketChannel socketChannel = null;
        try{
            socketChannel = (SocketChannel) key.channel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            int count = socketChannel.read(byteBuffer);
            if (count>0) {
                // 把缓冲区的数据读取成字符串
                String msg = new String(byteBuffer.array());
                System.out.println("读取到的数据 " + msg);
                // 向其他客户端发送消息
                sendMsgToOtherCilents(msg ,socketChannel);
            }
            System.out.println();
        }catch (Exception e) {
            e.printStackTrace();
            try{
                System.out.println(socketChannel.getRemoteAddress() + "离线了....");
                // 取消注册
                key.cancel();
                // 关闭通道
                serverSocketChannel.close();
            }catch (Exception ex) {
                ex.printStackTrace();
            }
        }

    }

    /**
     * 向其他客户端发送消息
     * @param msg
     * @param socketChannel
     */
    private void sendMsgToOtherCilents(String msg, SocketChannel socketChannel) throws IOException {
        System.out.println("消息转发给 : " +Thread.currentThread().getName());
        for (SelectionKey selectionKey : selector.keys()) {
            SelectableChannel channel = selectionKey.channel();
            if (channel instanceof SocketChannel && channel != socketChannel) {
                // 将channle 强转为
                SocketChannel returnChannel = (SocketChannel) channel;
                ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
                returnChannel.write(byteBuffer);
            }
        }

    }

    // 创建服务器对象
    public static void main(String[] args) throws IOException {
        NioServer nioServer = new NioServer();
        nioServer.listen();
    }

}
  1. 客户端的 创建
package src.com.NIO.groupchart;

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.StandardCharsets;
import java.util.Iterator;
import java.util.Scanner;

/**
 * nio 客户端
 */
public class NioCilent {

    private final String HOST = "127.0.0.1" ;
    private Selector selector;
    private SocketChannel socketChannel;
    private String username;
    private final int port = 6666;

    public NioCilent() throws IOException {
        selector = Selector.open();
        socketChannel = SocketChannel.open(new InetSocketAddress(HOST , port));
        socketChannel.configureBlocking(false);
        // 将channel 组测到 select
        socketChannel.register(selector , SelectionKey.OP_READ);
        username = socketChannel.getLocalAddress().toString().substring(1);
    }

    /**
     * 推送信息
     * @param info
     */
    public void sendInfo(String info) {
        info = username + ": say " + info;
        try {
            socketChannel.write(ByteBuffer.wrap(info.getBytes(StandardCharsets.UTF_8)));
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *  读取信息
     */
    public void readInfo() {
        try{
            int count = selector.select();
            if (count > 0) {
                Iterator<SelectionKey> iterators = selector.selectedKeys().iterator();
                while (iterators.hasNext()) {
                    SelectionKey key = iterators.next();
                    SocketChannel channel = (SocketChannel) key.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    channel.read(byteBuffer);
                    // 把读到的 缓冲区读取到
                    String str = new String(byteBuffer.array());
                    System.out.println(str.trim());
                    iterators.remove();
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws IOException {
        NioCilent nioCilent = new NioCilent();
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    nioCilent.readInfo();;
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }.start();

        //发送数据给服务器端
        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNextLine()) {
            String s = scanner.nextLine();
            nioCilent.sendInfo(s);
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值