现在的位置: 首页 > 综合 > 正文

JAVA NIO 笔记(2)

2012年11月08日 ⁄ 综合 ⁄ 共 2814字 ⁄ 字号 评论关闭

1.key.attachment为空?   sc.register(selector,  SelectionKey.OP_WRITE|SelectionKey.OP_READ,bb);  使用这种方法注册事件时,需要添加第三个参数:attachment对象;或者使用  key.interestOps(SelectionKey.OP_WRITE | SelectionKey.OP_READ)方法;  

2.如何捕捉到客户端断开事件?断开时会触发readable key,所以在isreadable中判断read的返回值是否为-1

3.如果不注册写事件则写操作无疑和同步方式一样了,如果注册了写事件则需要在写完时取消该事件

4.key.cancel会同时取消读与写事件 

package my;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
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.Iterator;

public class NIOS {
	public static final int SIZE = 1024;
	void start(int port) {
		ByteBuffer buffer = ByteBuffer.allocate(SIZE);
		try {
			ServerSocketChannel s = ServerSocketChannel.open();
			ServerSocket socket = s.socket();
			Selector selector = Selector.open();
			InetSocketAddress addr = new InetSocketAddress(port);
			socket.bind(addr);
			s.configureBlocking(false);
			s.register(selector, SelectionKey.OP_ACCEPT);
			while (true) {
				int selCount = selector.select();
				Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
				while (keys.hasNext()) {
					System.out.println("select Count:" + selCount);
					SelectionKey key = (SelectionKey) keys.next();
					keys.remove();
					if (key.isAcceptable()) {
						System.out.println("isacc...");
						ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
						SocketChannel sc = ssc.accept();
						sc.configureBlocking(false);
						sc.register(selector, SelectionKey.OP_READ);
					} else if (key.isReadable()) {
						System.out.println("readable..");
						SocketChannel sc = (SocketChannel) key.channel();
						try {
							
							int count = sc.read(buffer);
							System.out.println("Read byte:" + count);
							//log(buffer);
							if(count==SIZE){
								//如果count等于缓冲区大小,则说明此条消息没读完
								//需要设计复杂点的消息结构
								
							}else
							if (count == -1) {
								//当客户端断开连接时会触发read事件,并且可以读到-1,这时关闭通道
								sc.close();
								key.cancel();
								continue;
							}

						} catch (Exception e) {
							// TODO: handle exception
							sc.close();
							key.cancel();
							System.out.println("close!");
							continue;
						}
						buffer.flip();
						ByteBuffer bb = buffer.duplicate();
						key.attach(bb);
						buffer.clear();
						// sc.register(selector,
						// SelectionKey.OP_WRITE|SelectionKey.OP_READ,bb);
						//等价于
						key.interestOps(SelectionKey.OP_WRITE | SelectionKey.OP_READ);
						//通常不会注册写事件,除非写的内容巨大,注册写事件后注意取消
						
					} else if (key.isWritable()) {
						System.out.println("writable..");
						SocketChannel sc = (SocketChannel) key.channel();
						ByteBuffer att = (ByteBuffer) key.attachment();
						if (att.hasRemaining()) {
							int count = sc.write(att);
							System.out.println("write:" + count + " byte,hasRemain:" + att.hasRemaining());
						} else {
							//写完后取消可写事件,仅监听可读事件
							key.interestOps(SelectionKey.OP_READ);
						}
					}
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void log(ByteBuffer buf){
		try {
			System.out.println(new String(buf.array(),0,buf.limit(),"utf8"));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		new NIOS().start(802);
	}
}

JAVA NIO 笔记(1)

 

抱歉!评论已关闭.