技术开发 频道

使用Java NIO编写高性能的服务器

  该代码中,通过一个HandleClient来获取文件的一块数据,每一个客户都会分配一个HandleClient的实例。

  下面是客户端请求的代码,也比较简单,模拟100个用户同时下载文件。

  package nio.file;

  
import java.io.IOException;

  
import java.net.InetSocketAddress;

  
import java.nio.ByteBuffer;

  
import java.nio.CharBuffer;

  
import java.nio.channels.SelectionKey;

  
import java.nio.channels.Selector;

  
import java.nio.channels.SocketChannel;

  
import java.nio.charset.Charset;

  
import java.nio.charset.CharsetEncoder;

  
import java.util.Iterator;

  
import java.util.concurrent.ExecutorService;

  
import java.util.concurrent.Executors;

  
/**

  * 文件下载客户端

  *
@author tenyears.cn

  
*/

  
public class NIOClient {

  
static int SIZE = 100;

  
static InetSocketAddress ip = new InetSocketAddress("localhost",12345);

  
static CharsetEncoder encoder = Charset.forName("GB2312").newEncoder();

  
static class Download implements Runnable {

  
protected int index;

  
public Download(int index) {

  
this.index = index;

  }

  
public void run() {

  
try {

  
long start = System.currentTimeMillis();

  SocketChannel client
= SocketChannel.open();

  client.configureBlocking(
false);

  Selector selector
= Selector.open();

  client.register(selector, SelectionKey.OP_CONNECT);

  client.connect(ip);

  ByteBuffer buffer
= ByteBuffer.allocate(8 * 1024);

  
int total = 0;

  FOR:
for (;;) {

  selector.select();

  Iterator iter
= selector.selectedKeys()

  .iterator();

  
while (iter.hasNext()) {

  SelectionKey key
= iter.next();

  iter.remove();

  
if (key.isConnectable()) {

  SocketChannel channel
= (SocketChannel) key

  .channel();

  
if (channel.isConnectionPending())

  channel.finishConnect();

  channel.write(encoder.encode(CharBuffer

  .wrap(
"Hello from " + index)));

  channel.register(selector, SelectionKey.OP_READ);

  }
else if (key.isReadable()) {

  SocketChannel channel
= (SocketChannel) key

  .channel();

  
int count = channel.read(buffer);

  
if (count > 0) {

  total
+= count;

  buffer.clear();

  }
else {

  client.close();

  
break FOR;

  }

  }

  }

  }

  
double last = (System.currentTimeMillis() - start) * 1.0 / 1000;

  System.out.println(
"Thread " + index + " downloaded " + total

  
+ "bytes in " + last + "s.");

  }
catch (IOException e) {

  e.printStackTrace();

  }

  }

  }

  
public static void main(String[] args) throws IOException {

  ExecutorService exec
= Executors.newFixedThreadPool(SIZE);

  
for (int index = 0; index < SIZE; index++) {

  exec.execute(
new Download(index));

  }

  exec.shutdown();

  }

  }

 

  操作系统的API epoll, select, NonBlocking的IO就是对select(Unix平台下)以及 WaitForMultipleObjects(Windows平台)的封装,是OS级别下的支持。

0
相关文章