JavaNIO-ECHO模型

端口信息

public interface ServerInfo{
    public static final int SERVER_PORT = 9999 ;//设置一个服务端口
    public static final String SERVER_HOST = "localhost";//设置服务主机的名称
}

服务端

public class NIOEchoServer {
    public void start() throws Exception {//启动服务器
//        1考虑到线程性能的分配处理,所以创建一个定长的线程池
        ExecutorService service = Executors.newFixedThreadPool(32) ;//创建一个线程池
//        2如果要想实现服务端的开发,那么一定需要有一个服务端的Channel管理
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//开启服务端处理通道
        serverSocketChannel.configureBlocking(false);//设置为非阻塞模式
        serverSocketChannel.bind(new InetSocketAddress(ServerInfo.SERVER_PORT));//在当前主机中的9999端口绑定服务
//        3  开启一个选择器,所有的Channel都注册到此选择器之中,利用此选择器的循环来判断是否有新的连接
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//通道注册,连接的时候处理
//        4 、所有的用户的连接都要注册到当前的多路复用器上,那么就需要利用循环的模式来进行用户状态判断
        int keySelect = 0 ; //保存用户的判断状态
        while((keySelect = selector.select())>0){//持续进行等待,直到有用户连接上
            Set<SelectionKey> selectionKeySet =  selector.selectedKeys();//获取当前所有的连接的信息
            Iterator<SelectionKey> selectionKeyIterator = selectionKeySet.iterator();
            while (selectionKeyIterator.hasNext()){
                SelectionKey selectionKey = selectionKeyIterator.next();//获取当前的处理状态
                if(selectionKey.isAcceptable()){//当前为一个连接请求状态
                    SocketChannel socketChannel = serverSocketChannel.accept() ;//创建客户端通道
                    if(socketChannel !=null){
                        service.submit(new NIOEchoThread(socketChannel));//启动一个处理线程
                    }
                }
                selectionKeyIterator.remove();//已经进行了处理,所以不在需要做后续的轮询
            }
        }
        service.shutdown();
        serverSocketChannel.close();
    }

    public static void main(String[] args) throws Exception{
        new NIOEchoServer().start();//主方法只是一个启动
    }
}
class NIOEchoThread implements Runnable{
    private SocketChannel socketChannel ;
    private boolean flag = true ;
    public NIOEchoThread(SocketChannel socketChannel)throws Exception{
        this.socketChannel = socketChannel;
        System.out.println("【客户端连接成功】连接的客户端的地址为:"+this.socketChannel.getRemoteAddress());
    }
    @Override
    public void run() {
        ByteBuffer buffer = ByteBuffer.allocate(50);//开辟一个50大小的缓冲区
        try{
            while (this.flag){//持续循环
                buffer.clear();//清空缓冲区
                int readCount =this.socketChannel.read(buffer) ;
                String readMessage = new String(buffer.array(),0,readCount) ;
                System.out.println("【服务器端收到的消息】"+readMessage);
                String writeMessage = "【ECHO】"+readMessage;//设置回应的消息内容
                if("exit".equalsIgnoreCase(readMessage)){
                    writeMessage = "【EXIT】拜拜,下次再见";
                    this.flag = false ;//结束循环
                }
                buffer.clear();//之前已经读取过数据了,所以先清空缓冲区
                buffer.put(writeMessage.getBytes());//保存要回应的数据
                buffer.flip();//重置缓冲区
                this.socketChannel.write(buffer);
            }
            this.socketChannel.close();
        }catch (Exception e){}
    }
}

客户端

public class NIOEchoClient {
    public void start()throws Exception{
        SocketChannel socketChannel = SocketChannel.open() ;//开启Socket客户端通道
        //通过服务器端的主机名称和IP地址进行服务器端的操作连接
        socketChannel.connect(new InetSocketAddress(ServerInfo.SERVER_HOST,ServerInfo.SERVER_PORT));
        ByteBuffer buffer = ByteBuffer.allocate(50);//通过缓冲区进行交互
        boolean flag = true ;
        while (flag){
            buffer.clear() ;//清空缓冲区,因为该循环会持续执行
            String str = InputUtil.getString("请输入要发送的信息:") ;
            buffer.put(str.getBytes()) ;
            buffer.flip() ;//缓冲区重置
            socketChannel.write(buffer) ;
            buffer.clear();//清空缓冲区等待接收回应信息
            int readCount = socketChannel.read(buffer);//向缓冲区中读取数据
            System.err.println(new String(buffer.array(),0,readCount));
            if ("exit".equalsIgnoreCase(str)){
                flag = false ;//循环结束
            }
        }
        socketChannel.close();
    }
    public static void main(String[] args) throws Exception{
        new NIOEchoClient().start();
    }
}

class InputUtil { //    输入工具类
    public static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in));
    public static String getString(String prompt){
        String result = null ;
        while (result == null ||"".equals(result)){
            try {
                System.out.println(prompt);
                result = KEYBOARD_INPUT.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result ;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值