最近想学netty,但平常工作中NIO用的比较少,所以最近就
复习了下NIO。自己写了个基于NIO的echo
例子,代码挺简单的。
echo 服务端代码
class="java">
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();
}
}