Java NIO-Selector

一前言

                          以往服务端在读写文件时,都是对某个文件进行独占资源进行读取,如果这个操作没有完成,其他服务和请求无法对资源访问,阻塞其他请求和服务执行,显而易见,严重影响了服务器的处理,NIO中Seletor,channel,FileLock的出现,为服务器读取文件资源的性能提供了很大的改变。接下介绍Selector。


二 理论

                  以往的服务端I/O是通过读取本地文件,阻塞式访问。自从出现NIO后,可以建立服务器套接字连接通道,设置为非阻塞 传输模式,通过服务端套接字绑定服务的地址,服务器套接字通道设置选择其键值。在设置后,启动服务器端口,获取所有服务器端口的选择器的键,然后对每个端口的所有键值(已连接,已接受,可读,可写)进行迭代,在每个端口获取对应的键值状态后,进行相应操作服务区调用SocketChannel.read()。该方法将数据从SocketChannel 读到Buffer中。read()方法返回的int值表示读了多少字节进Buffer里。如果返回的是-1,表示已经读到了流的末尾(连接关闭了)。
 

package com.myd.cn.Nio;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
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.Date;
import java.util.Iterator;
import java.util.Set;


public class ServerSocketChannelDemo {
  

public static void main(String[] args) throws  Exception {
//设置服务器通道(初始化:端口,通道非阻塞,地址,设定seletor属性
//指定端口 
int serverPorts[] = {8000,8009,8090};
 
//通过selector.open()获取selector
Selector selector = Selector.open();
 
for (int i = 0; i < serverPorts.length; i++) {
//设置服务器通道实例
ServerSocketChannel initServer = null;
 
//打开服务器通道
initServer = ServerSocketChannel.open();

 
//设置服务器通道为非阻塞,就可用异步模式调用read(),write(),connect()

initServer.configureBlocking(false);
 
 
//设置服务器端套接字,用来下方的服务器与连接服务的绑定
 ServerSocket serverSocket = new ServerSocket();
 
//实力化绑定IP,端口地址
 InetSocketAddress inaAddress = new InetSocketAddress(serverPorts[i]);
 
//进行服务绑定,对应特定连接服务
 serverSocket.bind(inaAddress);
 
//设置selector键值为接受连接
 initServer.register(selector, SelectionKey.OP_ACCEPT);
 System.out.println("服务器运行,在" + serverPorts[i] + "端口监听。") ;
}
 
                 

 


//判断各个服务器端口是否已被选择,获取selector的键值,并判断他们的键值(是否已接受,已连接,可读的,可写的)
//进而进行详细的通过服务器通道写入服务端操作
 
int keyAdd = 0;
//判断各个服务器端口是否已被选择
while ((keyAdd=selector.select())>0) {
Set<SelectionKey> keys = selector.keys();
//迭代器键值集合,进行对应服务的处理(接受,连接,读写)
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
//已被选择获取selector的键值,并判断他们的键值(是否已接受,已连接,可读的,可写的)
SelectionKey key  = iterator.next();
if(key.isAcceptable()){
//如果已连接,则进行相应的操作

//通过key获取服务器套接字通道
ServerSocketChannel server = (ServerSocketChannel) key.channel();

//创建客户端套接字连接,亦为客户端连接实例  接受新连接,在返回套接字通道之前,会一直阻塞,一直到有新的连接达到
SocketChannel client = server.accept();


//设置通道为非阻塞
server.configureBlocking(false);
//进行写入操作,缓存区
ByteBuffer buf = ByteBuffer.allocateDirect(1024); //设置直接缓存区,进行快速读写

//放入数据
buf.put(("当前时间为:"+new Date()).getBytes()); //I/O以字节处理
//flip()重置操作,重新指定position(放入数据后,postion==limit ,limit<=capacity)
buf.flip();
//输出并写入内容 至客户端
client.write(buf);
//关闭缓存
buf.clear();
client.close();


}
}

keys.clear(); //清楚selector键值
   
}
}

}



客户端向服务器端的连接,可以自己写应用程序,也可以通过Telnet。

telnet localhost:8080




三总结

       总的来说,选择器的使用,提高了服务器处理业务的性能,由以往阻塞式,本地文件读取转完成非阻塞式,缓存读取文件内容的转换,明显的提高了服务器的I/O处理性能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值