Java nio 读取数据代码_Java NIO 读数据处理过程

packagesocket;importjava.io.IOException;importjava.net.InetSocketAddress;importjava.net.ServerSocket;importjava.nio.ByteBuffer;importjava.nio.channels.SelectionKey;importjava.nio.channels.Selector;importjava.nio.channels.ServerSocketChannel;importjava.nio.channels.SocketChannel;importjava.util.Iterator;importjava.util.Set;public classNIOServer2 {private void startServer() throwsIOException {

Selector selector=Selector.open();

{

ServerSocketChannel ssc=ServerSocketChannel.open();

ssc.configureBlocking(false);

ServerSocket ss=ssc.socket();

InetSocketAddress address= new InetSocketAddress(9000);

ss.bind(address);

System.out.println("ssc 0 : " +ssc);

System.out.println("ss 0 : " +ss);

SelectionKey acceptKey=ssc.register(selector, SelectionKey.OP_ACCEPT);

System.out.println("acceptKey: " +acceptKey);

printKeyInfo(acceptKey);

System.out.println("Going to listen on 9000");

}while (true) {

System.out.println("===================================\nstart select...");int num =selector.select();

System.out.println("NIOServer: Number of keys after select operation: " +num);

Set selectionKeys =selector.selectedKeys();

Iterator it =selectionKeys.iterator();while(it.hasNext()) {

SelectionKey key=it.next();

System.out.println("key: " +key);

printKeyInfo(key);

it.remove();if ((key.readyOps() & SelectionKey.OP_ACCEPT) ==SelectionKey.OP_ACCEPT) {

System.out.println("select ACCEPT");

ServerSocketChannel ssc=(ServerSocketChannel) key.channel();

SocketChannel sc=ssc.accept();

sc.configureBlocking(false);

System.out.println("ssc 1 : " +ssc);

System.out.println("sc 1 : " +sc);

SelectionKey newKey=sc.register(selector, SelectionKey.OP_READ);

System.out.println("new key:" +newKey);

printKeyInfo(newKey);

}else if ((key.readyOps() & SelectionKey.OP_READ) ==SelectionKey.OP_READ) {//System.out.println("select READ");//System.out.print("before cancel:");printKeyInfo(key);//key.cancel();//System.out.println("after cancel:");printKeyInfo(key);

SocketChannel sc =(SocketChannel) key.channel();

System.out.println("sc 2 : " +sc);//echo data//下面的处理是正确的,count<0则cancel key。count=0则进入下一轮select()阻塞等待数据。//try {//int count = doRead(key);//if (count < 0) {//key.cancel();//System.out.println("cancel key for < 0");//sc.read(ByteBuffer.allocate(2));//}//} catch(IOException e) {//e.printStackTrace();//key.cancel();//System.out.println("cancel key");//}//下面的处理过程是错误的,偶然情况下会出现正确逻辑。在客户端连续写,写完马上关闭连接,这时下面代码能打印出客户端的输出,//客户端关闭连接,下面的代码马上爆出异常,是这行代码。java.io.IOException: 您的主机中的软件中止了一个已建立的连接。//int nbytes = 0;//ByteBuffer echoBuffer = ByteBuffer.allocate(16);//while (true) {//echoBuffer.clear();//int r = sc.read(echoBuffer);//System.out.println(new String(echoBuffer.array()));//if (r <= 0) break;//echoBuffer.flip();//sc.write(echoBuffer);//nbytes += r;//}//System.out.println("echoed " + nbytes + " from " + sc);//下面的是处理过程是正确的。正确的做法就是对读取到n,0,-1分别处理,还要对客户端强制关闭的异常做处理

while (true) {

ByteBuffer buffer= ByteBuffer.allocate(2);

buffer.clear();intr;try{

r=sc.read(buffer);

System.out.println("r = " +r);

System.out.println(newString(buffer.array()));if (r < 0) {//客户端socket.close()会到这里,读取数r=-1

key.cancel();

System.out.println("cancel key for < 0");break;

}else if (r == 0) {//客户端socket没有关闭,而channel没有数据,数据数r=0。//有时候select()返回了,但channel不一定有数据。可能select()是被其他方法唤醒

break;

}

}catch(IOException e) {//客户端强制关闭会来这里报异常

e.printStackTrace();

key.cancel();

System.out.println("cancel key for Exception");break;

}

}//while

}//if ... else if//try {//Thread.sleep(500);//} catch (InterruptedException e) {//e.printStackTrace();//}

}//while

}//while

}private int doRead(SelectionKey key) throwsIOException {

SocketChannel channel=(SocketChannel) key.channel();while (true) {int count = -1;

ByteBuffer buffer= ByteBuffer.allocate(2);if (buffer.remaining() > 0) {

count=channel.read(buffer);

System.out.println("count = " +count);if (count <= 0) returncount;

}

}

}private static voidprintKeyInfo(SelectionKey sk) {

String s= newString();

s= "Att: " + (sk.attachment() == null ? "no" : "yes");

s+= ", Read: " +sk.isReadable();

s+= ", Acpt: " +sk.isAcceptable();

s+= ", Cnct: " +sk.isConnectable();

s+= ", Wrt: " +sk.isWritable();

s+= ", Valid: " +sk.isValid();

s+= ", interestOps: " +sk.interestOps();

s+= ", readyOps: " +sk.readyOps();

System.out.println(s);

}public static voidmain(String[] args) {try{newNIOServer2().startServer();

}catch(IOException e) {

e.printStackTrace();

}

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值