基于Nio的echo server和echo client

最近想学netty,但平常工作中NIO用的比较少,所以最近就复习了下NIO。自己写了个基于NIO的echo例子,代码挺简单的。


[size=medium][color=red]echo 服务端代码[/color][/size]

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();
}
}

}

}




[size=medium][color=red]echo 客户端代码[/color][/size]

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);
}

}
}

}



[size=medium][color=red]启动测试的代码[/color][/size]


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();
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值