nio demo

写了nio的demo


package com.io;

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.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

/**
 * mainReactor模型
 * mainReactor进行接收,然后dispatch给subReactor,由subReactor去定义selector,注册read事件
 * subReactor再dispatcher给executor
 * 
 * 针对nio中的异步,并不是操作系统说的内核准备数据,拷贝到用户进程缓存这个过程。
 * 而是用户线程没有得到数据,还可以继续往下执行。直到selector线程通过
 * 
 * io请求通用过程 read--decode--compute--encode--send
 * 
 * @author Administrator
 * 
 * 
 *
 */
public class NIOServer {
	public static void main(String[] args) {
		createServer();
	}

	public static void createServer() {
		TimeServer timeServer = new TimeServer();
		timeServer.start();
	}

	static class TimeServer extends Thread {
		// server
		private ServerSocketChannel serverSocketChannel;
		// 多路复用器,将channel注册到多路复用器,selector会不断的轮询注册在其上的channel,
		// 一旦某个channel上有读写事件,表示channel已经就绪,通过selectionKey可以获取就绪的channel集合
		//
		private Selector selector;

		public TimeServer() {
			try {
				selector = Selector.open();
				serverSocketChannel = ServerSocketChannel.open();
				// 配置是否阻塞
				serverSocketChannel.configureBlocking(false);
				// 绑定ip端口
				serverSocketChannel.socket().bind(new InetSocketAddress("127.0.0.1", 8888));
				// 注册accept到selector
				serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
			} catch (IOException e) {
				e.printStackTrace();
			}

		}

		@Override
		public void run() {

			try {
				// 这是个死循环,不断的轮询,没有阻塞
				while (true) {
					selector.select(1000);
					Set<SelectionKey> selectedKeys = selector.selectedKeys();
					Iterator<SelectionKey> iterator = selectedKeys.iterator();
					while (iterator.hasNext()) {
						SelectionKey selectionKey = iterator.next();
						// 移除已经就绪的selectionKey
						iterator.remove();
						handle(selectionKey);
					}
					// 清除已经轮询到的就绪的channel,或者在迭代器里面remove
					// selectedKeys.clear();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (selector != null) {
					try {
						selector.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}

		private void handle(SelectionKey selectionKey) throws IOException {
			if (selectionKey.isValid()) {
				if (selectionKey.isAcceptable()) {
					// 接收新请求
					ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
					SocketChannel sc = ssc.accept();
					sc.configureBlocking(false);
					// sc.register(selector, SelectionKey.OP_ACCEPT);
					sc.register(selector, SelectionKey.OP_READ);
				}

				if (selectionKey.isReadable()) {
					SocketChannel sc = (SocketChannel) selectionKey.channel();
					ByteBuffer readBuffer = ByteBuffer.allocate(1024);
					// channel操作buffer,channel.read
					int readBytes = sc.read(readBuffer);
					if (readBytes > 0) {
						readBuffer.flip();
						byte[] bytes = new byte[readBuffer.remaining()];
						readBuffer.get(bytes);
						String body = new String(bytes, "utf-8");
						System.out.println("The time server receive order:" + body);
						if ("get time".equals(body)) {
							String time = getNowDate();
							writeTime(sc, time);
						}
					} else if (readBytes < 0) {
						selectionKey.cancel();
						sc.close();
					} else {
						// 读到0字节,忽略
					}
				}
			}

		}

		/**
		 * channel操作buffer,channel.write
		 * 
		 * @param sc
		 * @param time
		 * @throws IOException
		 */
		private void writeTime(SocketChannel sc, String time) throws IOException {
			if (time != null && time.trim().length() > 0) {
				byte[] bytes = time.getBytes();
				ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
				writeBuffer.put(bytes);
				writeBuffer.flip();
				sc.write(writeBuffer);
			}
		}

		public static String getNowDate() {
			Date date = new Date();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.S");
			return sdf.format(date);
		}
	}
}
package com.io;

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.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NIOClient {
	public static void main(String[] args) {
		TimeClient timeClient = new TimeClient();
		timeClient.start();
	}

	static class TimeClient extends Thread {
		private SocketChannel socketChannel;
		private Selector selector;

		public TimeClient() {
			try {
				selector = Selector.open();
				socketChannel = SocketChannel.open();
				socketChannel.configureBlocking(false);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			try {
				doConnect();
			} catch (IOException e) {
				e.printStackTrace();
			}

			while (true) {
				try {
					selector.select(1000);
					Set<SelectionKey> set = selector.selectedKeys();
					Iterator<SelectionKey> iterator = set.iterator();
					while (iterator.hasNext()) {
						SelectionKey selectionKey = iterator.next();
						iterator.remove();
						try {
							handle(selectionKey);
						} catch (Exception e) {
							if (selectionKey != null) {
								selectionKey.cancel();
								if (selectionKey.channel() != null) {
									selectionKey.channel().close();
								}
							}
							e.printStackTrace();
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		private void handle(SelectionKey selectionKey) throws IOException {
			if (selectionKey.isValid()) {
				SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
				if (selectionKey.isConnectable()) {
					if (socketChannel.finishConnect()) {
						socketChannel.register(selector, SelectionKey.OP_READ);
						writeTime(socketChannel, "get time");
					}

				}

				if (selectionKey.isReadable()) {
					ByteBuffer readBuffer = ByteBuffer.allocate(1024);
					int readBytes = socketChannel.read(readBuffer);
					if (readBytes > 0) {
						readBuffer.flip();
						byte[] bytes = new byte[readBuffer.remaining()];
						readBuffer.get(bytes);
						String body = new String(bytes, "UTF-8");
						System.out.println("time is " + body);
					} else if (readBytes < 0) {
						selectionKey.cancel();
						socketChannel.close();
					} else {

					}
				}

			}

		}

		private void doConnect() throws IOException {
			// 连接到服务端
			boolean isConnected = socketChannel.connect(new InetSocketAddress("127.0.0.1", 8888));
			if (isConnected) {
				// 连接成功,注册read事件到selector
				socketChannel.register(selector, SelectionKey.OP_READ);
				writeTime(socketChannel, "get time");
			} else {
				socketChannel.register(selector, SelectionKey.OP_CONNECT);
			}
		}

		/**
		 * channel操作buffer,channel.write
		 * 
		 * @param sc
		 * @param time
		 * @throws IOException
		 */
		private void writeTime(SocketChannel sc, String time) throws IOException {
			if (time != null && time.trim().length() > 0) {
				byte[] bytes = time.getBytes();
				ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
				writeBuffer.put(bytes);
				writeBuffer.flip();
				sc.write(writeBuffer);
			}
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值