socket nio

 

package dock;
import java.io.IOException;
import java.net.InetSocketAddress;
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.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;
//学习网址
//http://ifeve.com/selectors/  浪迹v
//https://www.cnblogs.com/f1194361820/p/4019575.html   FangJinuo
//http://blog.csdn.net/canot/article/details/51372651  不能说的秘密go
//https://www.cnblogs.com/Theshy/p/7696313.html        不愿做一个代码机器的程序员
public class SocketNio {
	public static void main(String[] args) {
		try {
			SocketNio nio = new SocketNio();
			nio.init();
		} catch (IOException e) {
			System.out.println(e.toString());
		}
	}
	public void init() throws IOException {
		//Charset charset = Charset.forName("GBK");
		// 创建一个选择器,可用close()关闭,isOpen()表示是否处于打开状态,他不隶属于当前线程
		//AbstractSelector selector = SelectorProvider.provider().openSelector();
		Selector selector = Selector.open();
		// 创建ServerSocketChannel,并把它绑定到指定端口上
		ServerSocketChannel server = ServerSocketChannel.open();
		server.socket().bind(new InetSocketAddress(7777), 1024);
		// 设置为非阻塞模式, 这个非常重要
		server.configureBlocking(false);
		// 在选择器里面注册关注这个服务器套接字通道的accept事件
		// ServerSocketChannel只有OP_ACCEPT可用,OP_CONNECT,OP_READ,OP_WRITE用于SocketChannel
		server.register(selector, SelectionKey.OP_ACCEPT);
		while (true){
			selector.select(1000);
			Set<SelectionKey> keys = selector.selectedKeys();
			Iterator<SelectionKey> it = keys.iterator();
			SelectionKey key = null;
			while (it.hasNext()){
				// 如果key对应的Channel包含客户端的链接请求
				// OP_ACCEPT 这个只有ServerSocketChannel才有可能触发
				key = it.next();
				//由于select操作只管对selectedKeys进行添加,所以key处理后我们需要从里面把key去掉
				it.remove();
				if (key.isAcceptable()){
					ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
					// 得到与客户端的套接字通道
					SocketChannel channel = ssc.accept();
					channel.configureBlocking(false);
					channel.register(selector, SelectionKey.OP_READ);
					// 将key对应Channel设置为准备接受其他请求
					key.interestOps(SelectionKey.OP_ACCEPT);
				}
				if (key.isReadable()){
					key.interestOps(SelectionKey.OP_WRITE);
					//new Thread(new Task(key)){}.start();
					SocketChannel channel = (SocketChannel) key.channel();
					ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
					String content = "";
					try {
						int readBytes = channel.read(byteBuffer);
						if (readBytes > 0) {
							byteBuffer.flip(); // 为write()准备
							byte[] bytes = new byte[byteBuffer.remaining()];
							byteBuffer.get(bytes);
							content += new String(bytes);
							System.out.println(content);
							// 回应客户端
							doWrite(channel);
						}
						// 写完就把状态关注去掉,否则会一直触发写事件(改变自身关注事件)
						//key.interestOps(SelectionKey.OP_READ);
					} catch (IOException i) {
						// 如果捕获到该SelectionKey对应的Channel时出现了异常,即表明该Channel对于的Client出现了问题
						// 所以从Selector中取消该SelectionKey的注册
						key.cancel();
						if (key.channel() != null) {
							key.channel().close();
						}
					}
				}
			}
		}
	}
	//
	private void doWrite(SocketChannel sc) throws IOException {
		byte[] req = "服务器已接受\r\n".getBytes();
		ByteBuffer byteBuffer = ByteBuffer.allocate(req.length);
		byteBuffer.put(req);
		byteBuffer.flip();
		sc.write(byteBuffer);
		if (!byteBuffer.hasRemaining()) {
			System.out.println("Send 2 Service successed");
		}
		sc.close();
	}

	//读事件注释留底
	/*					SocketChannel channel = (SocketChannel) key.channel();
	ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
	String content = "";
	try {
		int readBytes = channel.read(byteBuffer);
		if (readBytes > 0) {
			byteBuffer.flip(); // 为write()准备
			byte[] bytes = new byte[byteBuffer.remaining()];
			byteBuffer.get(bytes);
			content += new String(bytes);
			System.out.println(content);
			// 回应客户端
			doWrite(channel);
		}
		// 写完就把状态关注去掉,否则会一直触发写事件(改变自身关注事件)
		//key.interestOps(SelectionKey.OP_READ);
	} catch (IOException i) {
		// 如果捕获到该SelectionKey对应的Channel时出现了异常,即表明该Channel对于的Client出现了问题
		// 所以从Selector中取消该SelectionKey的注册
		key.cancel();
		if (key.channel() != null) {
			key.channel().close();
		}
	}*/
}

  

posted on 2018-03-02 18:53  上雨  阅读(123)  评论(0编辑  收藏  举报

导航