JAVA NIO 笔记(2)

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)

 

你可能感兴趣的:(java NIO)