欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于Nio的echo server和echo client

程序员文章站 2022-07-10 15:02:28
...
最近想学netty,但平常工作中NIO用的比较少,所以最近就复习了下NIO。自己写了个基于NIO的echo例子,代码挺简单的。


echo 服务端代码
package study.nio.echo;

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.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EchoServer implements Runnable {

	private static final Logger LOGGER = LoggerFactory.getLogger(EchoServer.class);

	private Selector selector;

	private ServerSocketChannel serverSocketChannel;

	private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

	public EchoServer(int port) {

		try {

			selector = Selector.open();
			serverSocketChannel = ServerSocketChannel.open();
			serverSocketChannel.configureBlocking(false);
			serverSocketChannel.bind(new InetSocketAddress(port));
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

		} catch (IOException e) {

			LOGGER.error(e.getMessage());
			System.exit(0);
		}
	}

	@Override
	public void run() {

		if (selector.isOpen() == false) {

			LOGGER.warn("echo server selector is not start");
			return;
		}
		LOGGER.warn("echo server started");
		while (true) {

			try {

				selector.select();
				Set<SelectionKey> selectedKeys = selector.selectedKeys();
				Iterator<SelectionKey> keysIter = selectedKeys.iterator();
				while (keysIter.hasNext()) {

					SelectionKey key = keysIter.next();
					keysIter.remove();

					if (key.isAcceptable()) {

						ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
						SocketChannel sc = ssc.accept();
						sc.configureBlocking(false);
						LOGGER.info("echo server is connected");
						sc.register(selector, SelectionKey.OP_READ);
					} else if (key.isReadable()) {

						SocketChannel sc = (SocketChannel) key.channel();
						StringBuilder strb = new StringBuilder(1024);
						while (sc.read(byteBuffer) > 0) {

							byteBuffer.flip();
							byte[] bytes = new byte[byteBuffer.remaining()];
							byteBuffer.get(bytes);
							byteBuffer.clear();
							String msg = new String(bytes);
							LOGGER.info("echo server read msg:" + msg);
							strb.append(msg);
						}
						ByteBuffer writeBuffer = ByteBuffer.wrap(strb.toString().getBytes());
						LOGGER.info("{}", writeBuffer.position());
						LOGGER.info("{}", writeBuffer.limit());
						sc.write(writeBuffer);
					}
				}

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}





echo 客户端代码
package study.nio.echo;

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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class EchoClient implements Runnable {

	private static final Logger LOGGER = LoggerFactory.getLogger(EchoClient.class);

	private Selector selector;

	private SocketChannel socketChannel;

	private ByteBuffer byteBuffer;

	public EchoClient(String ip, int port) {

		try {
			selector = Selector.open();
			socketChannel = SocketChannel.open();
			socketChannel.configureBlocking(false);
			socketChannel.connect(new InetSocketAddress(ip, port));
			socketChannel.register(selector, SelectionKey.OP_CONNECT);
		} catch (IOException e) {

			LOGGER.error(e.getMessage());
			System.exit(0);
		}
	}

	@Override
	public void run() {

		if (selector.isOpen() == false) {
			
			LOGGER.warn("echo client selector is not start");
			return;
		}
		LOGGER.warn("echo client started");
		while (true) {

			try {
				if (selector.isOpen() == false) {
					 LOGGER.warn("selector is closed");
					 break;
				}
				selector.select();
				Iterator<SelectionKey> ite = this.selector.selectedKeys().iterator();
				while (ite.hasNext()) {

					SelectionKey key = (SelectionKey) ite.next();
					ite.remove();
					if (key.isConnectable()) {

						SocketChannel channel = (SocketChannel) key.channel();
						// 如果正在连接,则完成连接
						if (channel.isConnectionPending()) {
							channel.finishConnect();
						}
						LOGGER.info("echo client is connected");
						// 设置成非阻塞
						channel.configureBlocking(false);
						channel.write(ByteBuffer.wrap("this echo client msg,over".getBytes()));
						channel.register(selector, SelectionKey.OP_READ);
					} else if (key.isReadable()) {
						
						SocketChannel sc = (SocketChannel) key.channel();
						StringBuilder strb = new StringBuilder(1024);
						while (sc.read(byteBuffer) > 0) {

							byteBuffer.flip();
							byte[] bytes = new byte[byteBuffer.remaining()];
							byteBuffer.get(bytes);
							byteBuffer.clear();
							String msg = new String(bytes);
							strb.append(msg);
						}
						LOGGER.info("echo client read msg:" + strb.toString());
						break;
					}
				}

			} catch (IOException e) {
				
				LOGGER.error(e.getMessage());
				System.exit(0);
			}

		}
	}

}



启动测试的代码

package study.nio.echo;

public class EchoTest1 {

	public static void main(String[] args) {
		
		EchoClient echoClient = new EchoClient("127.0.0.1", EchoTest.serverPort);
		echoClient.run();
	}
}


package study.nio.echo;

public class EchoTest1 {

	public static void main(String[] args) {
		
		EchoClient echoClient = new EchoClient("127.0.0.1", EchoTest.serverPort);
		echoClient.run();
	}
}

相关标签: java nio