SocketChannel和Selector
非阻塞模式与选择器搭配会工作的更好,通过将一或多个SocketChannel注册到Selector,可以询问选择器哪个通道已经准备好了读取,写入等
上面已经分别介绍过SocketChannel和Selector 但是非阻塞模式与选择器搭配工作的代码没有整合。
如下就是非阻塞模式使用选择器的代码:
private static final int TIMEOUT = 3000;
private static final int BUF_SIZE=1024;
private static final int PORT = 9999;
@Test
public void test1() throws IOException, InterruptedException {
test("I'm 1st information from client");
}
@Test
public void test3() throws IOException, InterruptedException {
test("I'm 2st information from client");
}
public void test(String info) throws IOException, InterruptedException {
SocketChannel socketChannel = SocketChannel.open();
//设置为NIO
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("localhost", PORT));
ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
if(socketChannel.finishConnect())
{
while(true)
{
TimeUnit.SECONDS.sleep(1);
buf.clear();
buf.put(info.getBytes());
buf.flip();
while(buf.hasRemaining()){
socketChannel.write(buf);
}
}
}
}
@Test
public void test2() throws IOException {
Selector selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(PORT));
ssc.configureBlocking(false);
// int interestSet = SelectionKey.OP_READ & SelectionKey.OP_WRITE & SelectionKey.OP_ACCEPT;
ssc.register(selector,SelectionKey.OP_ACCEPT );
while(true){
if(selector.select(TIMEOUT) == 0){
System.out.println("==");
continue;
}
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while(iter.hasNext()){
SelectionKey key = iter.next();
if(key.isAcceptable()){
handleAccept(key);
}
if(key.isReadable()){
handleRead(key);
}
if(key.isWritable() && key.isValid()){
handleWrite(key);
}
if(key.isConnectable()){
System.out.println("isConnectable = true");
}
iter.remove();
}
}
}
public static void handleWrite(SelectionKey key) throws IOException{
ByteBuffer buf = (ByteBuffer)key.attachment();
buf.flip();
SocketChannel sc = (SocketChannel) key.channel();
while(buf.hasRemaining()){
sc.write(buf);
}
buf.compact();
}