Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIO #6

Open
cleverUtd opened this issue Dec 18, 2018 · 1 comment
Open

NIO #6

cleverUtd opened this issue Dec 18, 2018 · 1 comment

Comments

@cleverUtd
Copy link
Owner

cleverUtd commented Dec 18, 2018

NIO echo server

@cleverUtd
Copy link
Owner Author

package com.test;

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

/**
 * 单线程版本
 */
public class Test {

	public static void main(String[] args) throws Exception {
		Reactor reactor = new Reactor(9999);
		reactor.run();
	}


	static class Reactor implements Runnable {
		private final Selector selector;
		private final ServerSocketChannel serverSocket;

		public Reactor(int port) throws IOException {
			selector = Selector.open();
			serverSocket = ServerSocketChannel.open();
			serverSocket.socket().bind(new InetSocketAddress(port));
			serverSocket.configureBlocking(false);
			SelectionKey sk = serverSocket.register(selector, SelectionKey.OP_ACCEPT);
			// attach a Acceptor
			sk.attach(new Acceptor(serverSocket, selector));
		}


		@Override
		public void run() {
			while (!Thread.interrupted()) {
				try {
					selector.select();
					Set<SelectionKey> selected =  selector.selectedKeys();
					Iterator it = selected.iterator();
					while (it.hasNext()) {
						// dispatch
						SelectionKey sk = (SelectionKey) it.next();
						System.out.println("=========>acceptable=" + sk.isAcceptable() + ", "
								+ "readable=" + sk.isReadable() + ", "
								+ "writable=" + sk.isWritable());
						dispatch(sk);
					}
					selected.clear();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		private void dispatch(SelectionKey selectionKey) {
			Runnable task  = (Runnable) selectionKey.attachment();
			if (Objects.nonNull(task)) {
				task.run();
			}
		}
	}

	static class Acceptor implements Runnable {

		private final ServerSocketChannel serverSocket;
		private final Selector selector;

		public Acceptor(ServerSocketChannel serverSocket, Selector selector) {
			this.serverSocket = serverSocket;
			this.selector = selector;
		}

		@Override
		public void run() {
			try {
				System.out.println("Ready for accept!");
				SocketChannel socket = serverSocket.accept();
				if (Objects.nonNull(socket)) {
					//  passed to a new Handler
					new Handler(socket, selector);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	static class Handler implements Runnable {

		private SocketChannel socket;
		private SelectionKey sk;
		ByteBuffer input = ByteBuffer.allocate(1024);
		ByteBuffer output = ByteBuffer.allocate(1024);
		private final int READING = 0, SENDING = 1;
		private int state = READING;

		public Handler(SocketChannel s, Selector selector) {
			this.socket = s;
			try {
				s.configureBlocking(false);
				sk = socket.register(selector, 0);
				sk.attach(this);
				sk.interestOps(SelectionKey.OP_READ);
				selector.wakeup();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			try {
				if (state == READING) {
					read();
				} else if (state == SENDING) {
					send();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		private void read() throws IOException {
			socket.read(input);
			if (inputIsComplete()) {
				input.flip();
				process();
				state = SENDING;
				sk.interestOps(SelectionKey.OP_WRITE);
				input.rewind();
			}
		}

		private void send() throws IOException {
			output.put(input);
			output.flip();
			socket.write(output);
			if (outputIsComplete()) {
				output.rewind();
				byte[] bytes = new byte[output.remaining()];
				output.get(bytes);
				System.out.println("Send=" + new String(bytes).trim());
				state = READING;
				sk.interestOps(SelectionKey.OP_READ);
			}

			input.clear();
			output.clear();
		}

		private boolean inputIsComplete() {
			return true;
		}

		private boolean outputIsComplete() {
			return true;
		}

		private void process() {
			byte[] bytes = new byte[input.remaining()];
			input.get(bytes);
			System.out.println("Received====>" + new String(bytes).trim());
		}
	}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant