Step By Step(Java 网络篇) (三)

2014-11-24 03:03:08 · 作者: · 浏览: 4
cketChannel的OP_WRITE取消,而只是
52 //注册该SocketChannel的OP_READ事件,以等待客户端有新的请求数据发送过来。
53 if (!buf.hasRemaining()) {
54 key.interestOps(SelectionKey.OP_READ);
55 }
56 buf.compact();
57 } www.2cto.com
58 }
59
60 public class MyTest {
61 private static final int BUFSIZE = 256;
62 private static final int TIMEOUT = 3000;
63 public static void main(String[] args) throws IOException {
64 Selector selector = Selector.open();
65 //打开服务器监听SocketChannel
66 ServerSocketChannel listenChannel = ServerSocketChannel.open();
67 //绑定监听SocketChannel到指定的IP地址和端口
68 listenChannel.socket().bind(new InetSocketAddress("10.1.24.199", 5050));
69 listenChannel.configureBlocking(false);
70 //该监听SocketChannel只能注册OP_ACCEPT接收客户端连接的事件。
71 listenChannel.register(selector, SelectionKey.OP_ACCEPT);
72 TCPProtocal p = new SelectorProtocal(BUFSIZE);
73 while (true) {
74 //给当前的Selector实例设置超时,从而避免了忙等待现象,也避免了
75 //无限期阻塞的现象,当超时时,select函数返回0。
76 if (selector.select(TIMEOUT) == 0) {
77 System.out.print(".");
78 continue;
79 }
80 //此时已经有感知的事件发生了,通过selector获取所有事件集合的迭代器
81 Iterator keyIt = selector.selectedKeys().iterator();
82 while (keyIt.hasNext()) {
83 SelectionKey key = keyIt.next();
84 //判断事件的类型,是否为accept、read或者write
85 if (key.isAcceptable())
86 p.handleAccept(key);
87 if (key.isReadable())
88 p.handleRead(key);
89 if (key.isValid() && key.isWritable())
90 p.handleWrite(key);
91 //在处理完该事件之后需要从集合中主动移除该事件。
92 keyIt.remove();
93 }
94 }
95 }
96 }
该服务器示例代码同样也是学习性代码,不能实际用于真正的服务器程序中,因为该示例存在明显的性能缺陷和伸缩性问题。简单的说,handleWrite和handleRead等I/O操作和监听操作位于同一线程,如果连接的并发量较高时,将会有大量的客户端无法成功连接,因为此时该线程可能正在处理I/O操作。如果想解决该问题,常用的方法是为I/O(read/write)操作再新创建一个selector实例用以感知客户端的I/O事件,并在新的线程中负责该selector的select()调用。而当前的selector只是负责服务器监听SocketChannel的accept事件。与此同时,还需要增加一个线程池用以处理I/O事件,这样当host为多cpu和多核时,可以更加充分的利用硬件资源,从而提高服务器的运行效率和伸缩性。

摘自:Stephen Liu