nio服务端和客户端

nio服务端和客户端

服务端

public class NioServer implements Runnable {

	private ServerSocketChannel serverSocketChannel;
	private Selector selector;

	private ByteBuffer input = ByteBuffer.allocate(1024);
	private ByteBuffer out = ByteBuffer.allocate(1024);
	private String cache;

	public NioServer(int port) throws IOException {
		this.serverSocketChannel = ServerSocketChannel.open();
		serverSocketChannel.configureBlocking(false);
		serverSocketChannel.bind(new InetSocketAddress(port));
		selector = Selector.open();
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		System.out.println("server starts at port " + port);
	}


	@Override
	public void run() {
		while (true) {
			try {
				selector.select();
			} catch (IOException e) {
				e.printStackTrace();
			}
			Set<SelectionKey> selectionKeys = selector.selectedKeys();
			Iterator<SelectionKey> iterator = selectionKeys.iterator();
			while (iterator.hasNext()) {
				SelectionKey selectionKey = iterator.next();
				iterator.remove();
				if (!selectionKey.isValid()) {
					continue;
				}

				if (selectionKey.isAcceptable()) {
					try {
						SocketChannel socket = serverSocketChannel.accept();
						if (socket != null) {
							System.out.println("连接到服务器...");
						}
						socket.configureBlocking(false);
						socket.register(selector, SelectionKey.OP_READ);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

				if (selectionKey.isWritable()) {
					write(selectionKey);
				}

				if (selectionKey.isReadable()) {
					read(selectionKey);
				}
			}
		}
	}


	private void read(SelectionKey key) {
		try {
			SocketChannel channel = (SocketChannel) key.channel();
			int read = channel.read(input);
			if (read > 0) {
				input.flip();
				String result = new String(input.array(), 0, read, "UTF-8");
				cache = result;
				if ("bye".equals(result)) {
					key.channel();
					channel.close();
					System.out.println("客户端下线...");
					return;
				}
				System.out.println("server read[x]: " + result);
				input.clear();
				if (!channel.isOpen()) {
					System.out.println("客户端已经关闭连接...");
					return;
				}
				channel.register(selector, SelectionKey.OP_WRITE);
			} else {
				key.channel();
				channel.close();
				System.out.println("client read timeout...");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void write(SelectionKey key) {

		SocketChannel channel = (SocketChannel) key.channel();
		try {
			String result = "echo from server[x]: " + cache;
			System.out.println("server send[x]: " + result);
			out.put(result.getBytes());
			out.flip();
			channel.write(out);
			out.clear();
			if (!channel.isOpen()) {
				System.out.println("客户端已经关闭连接...");
				return;
			}
			channel.register(selector, SelectionKey.OP_READ);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


客户端

public class NioClient implements Runnable {

	private SocketChannel socketChannel;
	private Selector selector;
	private boolean stop = false;

	private ByteBuffer input = ByteBuffer.allocate(1024);
	private ByteBuffer out = ByteBuffer.allocate(1024);


	public NioClient(String ip, int port) throws IOException {
		socketChannel = SocketChannel.open();
		socketChannel.configureBlocking(false);
		selector = Selector.open();
		socketChannel.connect(new InetSocketAddress(ip, port));
		socketChannel.register(selector, SelectionKey.OP_CONNECT);
	}


	@Override
	public void run() {

		while (!stop) {
			try {
				selector.select();
			} catch (IOException e) {
				e.printStackTrace();
			}
			Set<SelectionKey> selectionKeys = selector.selectedKeys();
			Iterator<SelectionKey> iterator = selectionKeys.iterator();
			while (iterator.hasNext()) {
				try {
					SelectionKey selectionKey = iterator.next();
					iterator.remove();

					if (!selectionKey.isValid()) {
						continue;
					}

					if (selectionKey.isConnectable()) {
						SocketChannel sc = (SocketChannel) selectionKey.channel();
						if (socketChannel.isConnectionPending()) {
							System.out.println("正在连接...");
							sc.finishConnect();
						}

						System.out.println("客户端连接成功...");
						sc.configureBlocking(false);
						sc.register(selector, SelectionKey.OP_WRITE);
					}

					if (selectionKey.isReadable()) {
						read(selectionKey);
					}

					try {
						if (selectionKey.isWritable()) {
							write(selectionKey);
						}
					} catch (CancelledKeyException e) {
						selectionKey.cancel();
						stop = true;
						break;
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private void read(SelectionKey key) {
		try {
			SocketChannel channel = (SocketChannel) key.channel();
			int read = channel.read(input);
			if (read > 0) {
				input.flip();
				String result = new String(input.array(), 0, read, "UTF-8");
				System.out.println("client read[x]: " + result);
				input.clear();
				if (!channel.isOpen()) {
					System.out.println("主动关闭连接...");
					return;
				}
				channel.register(selector, SelectionKey.OP_WRITE);
			} else {
				key.cancel();
				channel.close();
				System.out.println("client read timeout....");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void write(SelectionKey key) {

		SocketChannel channel = (SocketChannel) key.channel();
		try {
			Scanner scanner = new Scanner(System.in);
			String result = scanner.next();
			System.out.println("client send[x]: " + result);
			out.put(result.getBytes());
			out.flip();
			channel.write(out);
			out.clear();
			if (!channel.isOpen()) {
				System.out.println("主动关闭连接...");
				return;
			}

			channel.register(selector, SelectionKey.OP_READ);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

测试

new Thread(new NioServer(9090)).start();
new Thread(new NioClient("localhost", 9090)).start();

结果:

# server

server starts at port 9090
连接到服务器...
server read[x]: hello
server send[x]: echo from server[x]: hello
server read[x]: 你好
server send[x]: echo from server[x]: 你好
客户端下线...

当客户端输入bye的时候退出

# client

正在连接...
客户端连接成功...
hello
client send[x]: hello
client read[x]: echo from server[x]: hello
你好
client send[x]: 你好
client read[x]: echo from server[x]: 你好
bye
client send[x]: bye
client read timeout....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值