server:
package com.tang.selector;
import java.io.IOException;
import java.net.InetSocketAddress;
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 java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Created by TangXW on 2017/8/11.
*/
public class TimeServer {
private static ExecutorService executor;
static{
executor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000));
}
public static void main(String[] args) throws IOException{
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(8080));
ssc.configureBlocking(false);
Selector selector = Selector.open();
ssc.register(selector, ssc.validOps());
while(true){
// 如果不设置连接超时,那么这个方法一直是阻塞的
int readCount = selector.select(1000);
if(readCount == 0){
continue;
}
Set<SelectionKey> selectionKeySets = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectionKeySets.iterator();
while(keyIterator.hasNext()){
SelectionKey selectionKey = keyIterator.next();
if(selectionKey.isValid()){ // 此键是否有效
// 表示是serversocketchannel
if(selectionKey.isAcceptable()){
ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel();
SocketChannel socketChannel = server.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
}
// 表示SocketChannel
if(selectionKey.isReadable()){
executor.submit(new TimeServerTask(selectionKey));
}
keyIterator.remove();
}
}
}
}
}
servertask:
package com.tang.selector;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Calendar;
/**
* Created by TangXW on 2017/8/11.
*/
public class TimeServerTask implements Runnable{
private SelectionKey selectionKey;
public TimeServerTask(SelectionKey selectionKey){
this.selectionKey = selectionKey;
}
@Override
public void run() {
SocketChannel channel = (SocketChannel) selectionKey.channel();
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
try{
int count = 0;
// 如果从socketchannel中有数据
while((count = channel.read(byteBuffer)) > 0){
byteBuffer.flip();
byte[] request = new byte[byteBuffer.remaining()];
byteBuffer.get(request);
String requestStr = new String(request);
byteBuffer.clear();
if(!"GET CURRENT TIME".equals(requestStr)){
channel.write(byteBuffer.put("BAD_REQUEST".getBytes()));
}else{
// 写入当前的时间戳
byteBuffer.put(Calendar.getInstance().getTime().toLocaleString().getBytes());
byteBuffer.flip();
channel.write(byteBuffer);
}
}
} catch (IOException e){
e.printStackTrace();
selectionKey.cancel();
}
}
}
client:
package com.test.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
/**
* Created by TangXW on 2017/8/11.
*/
public class TimeClient2 {
//连接超时时间
static int connectTimeOut = 3000;
static ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
public static void main(String[] args) throws IOException, InterruptedException {
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(8080));
socketChannel.configureBlocking(false);
long start = System.currentTimeMillis();
while (!socketChannel.finishConnect()){
if (System.currentTimeMillis() - start >= connectTimeOut){
throw new RuntimeException("尝试建立连接超过3秒");
}
}
// 如果走到这一步,说明连接建立成功
while (true){
buffer.put("GET CURRENT TIME".getBytes());
buffer.flip();
socketChannel.write(buffer);
buffer.clear(); // 清空然后将传过来的数据重新写入
if(socketChannel.read(buffer) > 0){
buffer.flip();
byte[] response = new byte[buffer.remaining()];
buffer.get(response);
System.out.println("reveive response:" + new String(response));
buffer.clear();
}
Thread.sleep(5000);
}
}
}
output:
reveive response:2017-8-14 13:33:31
reveive response:2017-8-14 13:33:36
reveive response:2017-8-14 13:33:41
reveive response:2017-8-14 13:33:46
reveive response:2017-8-14 13:33:51
...