Java NIO

目录

        IO多路复用技术(其他IO模型详见:IO模型篇章)

        JAVA NIO

        Selector:Channel的管理器

        Channel

                读取文件

                网络编程中的使用

        Buffer


IO多路复用技术(其他IO模型详见:IO模型篇章)

 

        selector会替代应用程序,轮询一批注册到selector中的文件描述符(套接字,标准输入输

出),只要有部分文件描述符的数据准备就绪,就通知用户程序。

        linux系统的selector由select,poll,epoll方式实现;

        select 的缺点:

        1,每次调用 select,都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大

        2,每次调用 select 都需要在内核遍历传递进来的所有 fd,这个开销在 fd 很多时也很大

        3,select 支持的文件描述符数量,默认是1024

        epoll(Linux 2.6内核正式引入,用于代替 select 和 poll 系统调用):

        1,内核与用户空间共享一块内存

        2,通过回调解决遍历问题

        3,fd 没有限制,可以支撑10万连接

JAVA NIO

        NIO:非阻塞IO,多路复用技术;

Selector:Channel的管理器

        Selector允许单线程处理多个 Channel

        Selector是一个对象,Channel可以注册到Selector,Selector监听各个Channel上发生的事

件,并且能够根据事件情况决定Channel读写。

Channel

        Java NIO中Channel主要有如下几种类型:

        FileChannel:从文件读取数据的;(通过FileInputStream,FileOutputStream,

RandomAccessFile中获取)

        DatagramChannel:读写UDP网络协议数据

        SocketChannel:读写TCP网络协议数据;

        ServerSocketChannel:可以监听TCP连接;

        读取文件

        RandomAccessFile file = new RandomAccessFile("test.txt", "rw");

        FileChannel fileChannel = file.getChannel();

        ByteBuffer buf = ByteBuffer.allocate(1024);

        int bytesRead = fileChannel.read(buf);

        网络编程中的使用

        底层实现代码

...
// 监听socketServer的文件描述符
listen_fd = tcp_server_listen(SERV_PORT);
...
// 把上述文件描述符,添加到文件描述符集合中
struct pollfd event_set[INIT_SIZE]; 
event_set[0].fd = listen_fd; 
event_set[0].events = POLLRDNORM;
...
for (;;) {
 //调用poll函数,轮询文件描述符集合,进行事件检测
    if ((ready_number = poll(event_set, INIT_SIZE, -1)) < 0) { 
        error(1, errno, "poll failed "); 
    }
 
 
    if (event_set[0].revents & POLLRDNORM) { 
        socklen_t client_len = sizeof(client_addr); 
        //socketServer监听,如果有链接事件,创建socket链接描述符
        connected_fd = accept(listen_fd, (struct sockaddr *) &client_addr, &client_len); 
        //把socket链接描述符,添加到描述符集合中;
        for (i = 1; i < INIT_SIZE; i++) { 
            if (event_set[i].fd < 0) { 
                event_set[i].fd = connected_fd; 
                event_set[i].events = POLLRDNORM; 
                break; 
            } 
        }
    }
 
    // 链接描述符,读写数据
    for (i = 1; i < INIT_SIZE; i++) {
        if (event_set[i].revents & (POLLRDNORM | POLLERR)) { 
            if ((n = read(socket_fd, buf, MAXLINE)) > 0) { 
                if (write(socket_fd, buf, n) < 0) { 
                    error(1, errno, "write error"); 
                } 
            } else if (n == 0 || errno == ECONNRESET) { 
                close(socket_fd); event_set[i].fd = -1; 
            } else { 
                error(1, errno, "read error"); 
            }
        }
    }
}

        Java封装之后的使用代码

ServerSocketChannel ssc = ServerSocketChannel.open();

ssc.socket().bind(new InetSocketAddress(port));

while(true){

    SocketChannel sc = ssc.accept();

    ByteBuffer buffer = ByteBuffer.wrap("data".getBytes());

    sc.write(buffer);

}

Buffer

        读写数据的缓存空间。

        应用程序不能直接对Channel进行读写操作,而必须通过Buffer来进行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值