经过上面步骤后该ServerSocketChannel可以接受客户端的连接请求但我们需要调用Selector的select()方法来监听所有Channel上的IO操作
程序清单codes///NoBlock/NServerjava
public class NServer
{
//用于检测所有Channel状态的Selector
private Selector selector = null;
//定义实现编码解码的字符集对象
private Charset charset = CharsetforName(UTF)
public void init()throws IOException
{
selector = Selectoropen()
//通过open方法来打开一个未绑定的ServerSocketChannel实例
ServerSocketChannel server = ServerSocketChannelopen()
InetSocketAddress isa = new InetSocketAddress(
)
//将该ServerSocketChannel绑定到指定IP地址
serversocket()bind(isa)
//设置ServerSocket以非阻塞方式工作
serverconfigureBlocking(false)
//将server注册到指定Selector对象
serverregister(selector SelectionKeyOP_ACCEPT)
while (selectorselect() > )
{
//依次处理selector上的每个已选择的SelectionKey
for (SelectionKey sk : selectorselectedKeys())
{
//从selector上的已选择Key集中删除正在处理的SelectionKey
selectorselectedKeys()remove(sk) //①
//如果sk对应的通道包含客户端的连接请求
if (skisAcceptable()) //②
{
//调用accept方法接受连接产生服务器端对应的SocketChannel
SocketChannel sc = serveraccept()
//设置采用非阻塞模式
scconfigureBlocking(false)
//将该SocketChannel也注册到selector
scregister(selector SelectionKeyOP_READ)
//将sk对应的Channel设置成准备接受其他请求
skinterestOps(SelectionKeyOP_ACCEPT)
}
//如果sk对应的通道有数据需要读取
if (skisReadable()) //③
{
//获取该SelectionKey对应的Channel该Channel中有可读的数据
SocketChannel sc = (SocketChannel)skchannel()
//定义准备执行读取数据的ByteBuffer
ByteBuffer buff = ByteBufferallocate()
String content = ;
//开始读取数据
try
{
while(scread(buff) > )
{
buffflip()
content += charsetdecode(buff)
}
//打印从该sk对应的Channel里读取到的数据
Systemoutprintln(===== + content)
//将sk对应的Channel设置成准备下一次读取
skinterestOps(SelectionKeyOP_READ)
}
//如果捕捉到该sk对应的Channel出现了异常即表明该Channel
//对应的Client出现了问题所以从Selector中取消sk的注册
catch (IOException ex)
{
//从Selector中删除指定的SelectionKey
skcancel()
if (skchannel() != null)
{
skchannel()close()
}
}
//如果content的长度大于即聊天信息不为空
if (contentlength() > )
{
//遍历该selector里注册的所有SelectKey
for (SelectionKey key : selectorkeys())
{
//获取该key对应的Channel
Channel targetChannel = keychannel()
//如果该channel是SocketChannel对象
if (targetChannel instanceof SocketChannel)
{
//将读到的内容写入该Channel中
SocketChannel dest = (SocketChannel)targetChannel;
destwrite(charsetencode(content))
}
}
}
}
}
}
}
public static void main(String[] args)
throws IOException
{
new NServer()init()
}
}
上面程序启动时即建立一个可监听连接请求的ServerSocketChannel并将该Channel注册到指定Selector接着程序直接采用循环不断监控Selector对象的select()方法返回值当该返回值大于时处理该Selector上所有被选择的SelectionKey
开始处理指定SelectionKey之后立即从该Selector中的被选择的SelectionKey集合中删除该SelectionKey如程序中①号代码所示
[] []