NIO Server简单实现

Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。

Java NIO: Channels and Buffers(通道和缓冲区)

标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

Java NIO: Non-blocking IO(非阻塞IO)

Java NIO可以让你非阻塞的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。

Java NIO: Selectors(选择器)

Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。

package com.xxx.xxxController;

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.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NioServer {
    private Selector selector;

    public void initServer(String adrress, int port) throws IOException {
        //1:建立一个Socket连接通道
        ServerSocketChannel nioSocketChannel = ServerSocketChannel.open();
        //2: 将连接设置成非阻塞
        nioSocketChannel.configureBlocking(false);
        //3: 绑定socket监听地址
        nioSocketChannel.socket().bind(new InetSocketAddress(adrress, port));
        //4: 获取通道管理器
        this.selector = Selector.open();
        //5: 将通道与管理器绑定, 并注册SelectionKey.OP_ACCEPT事件
        nioSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
    }

    public void listen() throws IOException {
        System.out.println("server started");
        while (true) {
            //监听客户端事件,阻塞
            selector.select();
            Set<SelectionKey> keySet =  selector.selectedKeys();
            //处理客户端连接和请求
            Iterator<SelectionKey> it = keySet.iterator();
            while (it.hasNext()) {
                SelectionKey key = it.next();
                it.remove();
                handler(key);
            }
        }
    }

    public void handler(SelectionKey key) throws IOException {
        if(key.isAcceptable()) {
            handlerAccept(key);
        } else if(key.isReadable()) {
            handlerRead(key);
        }
    }

    public void handlerAccept(SelectionKey key) throws IOException {
        //获取Key上绑定的通道
        ServerSocketChannel nioSocketChannel = (ServerSocketChannel) key.channel();
        //监听连接并返回连接的通道,非阻塞通道直接返回
        SocketChannel acceptChannel = nioSocketChannel.accept();
        acceptChannel.configureBlocking(false);

        System.out.println("new client accepted");

        //将通道与管理器绑定, 并注册SelectionKey.OP_事件
        acceptChannel.register(this.selector, SelectionKey.OP_READ);
    }

    public void handlerRead(SelectionKey key) throws IOException {
        SocketChannel readChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int read =  readChannel.read(buffer);
        if(read > 0) {
            byte[] data = buffer.array();
            String msg = new String(data).trim();
            System.out.println("clent sent msg :" + msg);

            ByteBuffer outBuffer = ByteBuffer.wrap("msg confirmed!".getBytes());
            readChannel.write(outBuffer);
        } else {
            System.out.println("客户端关闭");
            key.cancel();
        }

    }

    public static void main(String[] args){
        NioServer nioServer = new NioServer();
        try {
            nioServer.initServer("127.0.0.1", 8888);
            nioServer.listen();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 
使用telnet客户端  telnet 127.0.0.1 8888
    
    输出结果:
    server started
    new client accepted
    clent sent msg :s
    clent sent msg :d
    clent sent msg :m
    clent sent msg :q
    客户端关闭

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值