import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Created by lsy
* on 2020/1/13 16:13.
*/
public class MultipleTimeClient implements Runnable {
private SocketChannel socketChannel;
private Selector selector;
private volatile boolean stop = false;
private int port;
public MultipleTimeClient(int port) {
this.port = port;
try {
socketChannel = SocketChannel.open();
selector = Selector.open();
socketChannel.configureBlocking(false);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
// 处理连接
boolean connect = socketChannel.connect(new InetSocketAddress("127.0.0.1", port));
if (connect) {
// 对读事件设置感兴趣
socketChannel.register(selector, SelectionKey.OP_READ);
// 连接上了,开始写入数据
doWrite(socketChannel);
} else {
doConnect();
}
} catch (IOException e) {
e.printStackTrace();
}
while (!stop) {
// 连上了,处理读出来的东西
try {
selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
handleInput(key);
}
} catch (IOException e) {
e.printStackTrace();
stop = true;
}
}
if (selector != null) {
try {
selector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void handleInput(SelectionKey key) {
if (key.isConnectable()) {
try {
if (socketChannel.finishConnect()) {
socketChannel.register(selector, SelectionKey.OP_READ);
doWrite(socketChannel);
} else {
System.out.println("client cant connet to server " + port);
System.exit(1);
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 处理了读,记得处理连接啊
if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
try {
if (channel.finishConnect()) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
int size = channel.read(byteBuffer);
if (size > 0) {
byteBuffer.flip(); // 和下面那句顺序不可以乱的
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
String s = new String(bytes, "UTF-8");
System.out.println("client receive : " + s);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
doWrite(socketChannel);
} else if (size < 0) {
key.cancel();
channel.close();
}
}
} catch (IOException e) {
e.printStackTrace();
stop = true;
}
}
}
private void doWrite(SocketChannel socketChannel) {
String message = "time";
ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
try {
socketChannel.write(buffer);
if (!buffer.hasRemaining()) {
System.out.println("send to server success");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void doConnect() {
// 本质就是发送一个链接位置的event
try {
socketChannel.register(selector, SelectionKey.OP_CONNECT);
} catch (ClosedChannelException e) {
e.printStackTrace();
}
}
}
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.Date;
import java.util.Iterator;
import java.util.Set;
/**
* Created by lsy
* on 2020/1/13 15:29.
*/
public class MultipleTimeServer implements Runnable {
private ServerSocketChannel serverSocketChannel;
private Selector selector;
private volatile boolean stop = false;
public MultipleTimeServer(int port) {
try {
serverSocketChannel = ServerSocketChannel.open();
selector = Selector.open();
// 设置非阻塞模式
serverSocketChannel.configureBlocking(false);
// 绑定端口
serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", port));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("TimeServer start in port : " + port);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (!stop) {
try {
selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isAcceptable()) {
// 链接处理
handleAccept(key);
} else if (key.isReadable()) {
// 读处理
handleRead(key);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void handleRead(SelectionKey key) {
SocketChannel channel = (SocketChannel) key.channel();
// 开始读取
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
try {
int size = channel.read(byteBuffer);
if (size > 0) {
// 读取到了数据
byteBuffer.flip(); // 这句很重要啊,设置游标,不然get获取不了数据
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
String request = new String(bytes, "UTF-8");
System.out.println("server receive order" + request);
String curr = "time".equals(request) ? new Date().toString() : "bad order";
// 回写当前时间
doWrite(channel, curr);
} else if (size < 0) {
// 等于-1代表关闭了链接
key.cancel();
serverSocketChannel.close();
} else {
// 没有数据,正常情况,抛弃处理
}
} catch (IOException e) {
e.printStackTrace();
// 读发生异常,关闭channel
try {
channel.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private void doWrite(SocketChannel channel, String curr) {
ByteBuffer writeBuffer = ByteBuffer.wrap(curr.getBytes());
try {
channel.write(writeBuffer);
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleAccept(SelectionKey key) {
ServerSocketChannel channel = (ServerSocketChannel) key.channel();
// 使用accept获得SocketChannel
try {
SocketChannel socketChannel = channel.accept();
socketChannel.configureBlocking(false);
// 并且注册到多路复用器
socketChannel.register(selector, SelectionKey.OP_READ);
System.out.println("server handle accept event");
} catch (IOException e) {
e.printStackTrace();
}
}
}