NIO的问题,懂的大神来解释下

沁海棠 2017-05-14 10:16:31
/**
*
* 通道非阻塞模式的切换
* 如果要切换到非阻塞模式,那么通道,缓冲区,选择器都需要,nio的核心
*/
public class NotBlock {
@Test
public void client(){
SocketChannel cl = null;
try {
//获取通道
cl = SocketChannel.open(new InetSocketAddress("127.0.0.1",8888));
//切换非阻塞模式
cl.configureBlocking(false);
//分配指定大小的缓冲区
ByteBuffer data = ByteBuffer.allocate(1024);
//发送数据
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
data.put("123".getBytes());
data.flip();
cl.write(data);
cl.shutdownOutput();
data.clear();
//关闭通道
cl.close();
} catch (IOException e) {
e.printStackTrace();
}

}
@Test
public void server(){
ServerSocketChannel se = null;
try {
//获取通道
se = ServerSocketChannel.open();
//切换非阻塞模式
se.configureBlocking(false);
//绑定链接
se.bind(new InetSocketAddress(8888));
//获取选择器选择器
Selector select = Selector.open();
/*将通道注册到选择器上,第一个参数是选择器,第二个参数称为选择键,selectionKey
* 它有四个常量来表示监听的状态读read 写write 链接connect 接受accept
* 如果一个监听器监听 不只一个事件可用或运算符链接
* 阻塞的server直接就是阻塞等待客户链接
* accept是已经完成了链接,connect是有链接过来
*/
se.register(select, SelectionKey.OP_ACCEPT);
/**
* 轮训监听器上准备就绪的事件
*/
int ll = 0;
while((ll=select.select())>0){
//获取当前选择器中注册的 选择键 (已就绪的监听事件)返回一个selecttionKey集合里面包含了感情去的事件
Iterator<SelectionKey> i = select.selectedKeys().iterator();
//遍历事件
System.out.println("阻塞");
while(i.hasNext()){
//获取就绪的事件
System.out.println("刚开始"+ll);
SelectionKey sk = i.next();
//选择器可以注册多个事件,判断这个事件是什么事件
if(sk.isAcceptable()){
//如果接受就绪,那么就让服务和客户端链接
SocketChannel client = se.accept();
//接受到的用户链接切换的非阻塞模式
client.configureBlocking(false);
//把这个用户通道也注册到选择器
client.register(select, SelectionKey.OP_READ);
System.out.println("添加链接");
}else if(sk.isReadable()){
//如果是读就绪,那么在让客户端来读取这样就不会阻塞了
SocketChannel sclie = (SocketChannel) sk.channel();
//读取数据
ByteBuffer data = ByteBuffer.allocate(1024);
int len=0;
while((len=sclie.read(data))!=-1){
data.flip();
System.out.println(new String(data.array(),0,len));
data.clear();
System.out.println("读数据"+len);
}
sclie.shutdownInput();
System.out.println("读数据完成"+len);
}
//取消选择键,
System.out.println(i.hasNext()+"遍历完一个"+ll);
i.remove();
}
}
System.out.println("准备好的通道有"+ll);
} catch (IOException e) {
System.out.println("执行玩了");
e.printStackTrace();
}

}
}

跟着视频写的,第一个问题,客户端非阻塞有什么用?第二个问题,去掉remove()客户端执行完毕后,客户端执行完毕 数据有时候会接受有时候不会(我想执行完毕是因为accept()跟新返回的数据是0,有时候没有接受到数据是因为增加通道监听通道是否可读,客户端延时没有发送数据,accept()去更新准备好的通道数据,发现没有准备好的循环完毕,这时我就想在最后看一下accept的值,但是总是不会执行 System.out.println("准备好的通道有"+ll); )第三个问题加上remove()在客户端执行完毕后,服务端无限的循环,一直认为通道是可读的,这里就更晕了,客户端单方面的关闭了通道,服务端还有通道,并且认为是可读的,是因为在开始读数据的时候,并不能判断数据是否到末尾,然后我在客户端有加了cl.shutdownOutput(); 然而并没什么卵用,accept 每次更新都认为通道是可读的一直循环,难道不remove在偶尔接受到数据后为什么不会陷入循环
总之晕的稀里糊涂
谁给详细解释下到时啥意思
跪求大神
万分感谢
...全文
143 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
沁海棠 2017-05-14
  • 打赏
  • 举报
回复
想不明白的就是remove后会继续执行,不remove为什么会终止,循环外最后的语句为什么不执行!

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧