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