浏览 15098 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (16) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-09-20
最后修改:2010-09-20
public class NIODemo { private final Selector selector; private CharsetEncoder encoder = Charset.forName("utf-8").newEncoder(); protected CharsetDecoder decoder; public NIODemo() throws IOException { Charset charset = Charset.forName("utf-8"); decoder = charset.newDecoder(); selector = Selector.open(); } public void fetch() throws IOException { SocketChannel client = SocketChannel.open(); client.configureBlocking(false); InetSocketAddress address = new InetSocketAddress("127.0.0.1", 80); client.register(selector, SelectionKey.OP_CONNECT); client.connect(address); } public void start() throws IOException { Executors.newSingleThreadExecutor().execute(new Runnable() { @Override public void run() { try { while (true) { System.out.println("before select."); selector.select(); System.out.println("after select."); Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); iterator.remove(); handleKey(key); } } } catch (IOException e) { e.printStackTrace(); } } }); } private void handleKey(SelectionKey key) throws IOException { SocketChannel channel = (SocketChannel) key.channel(); if (key.isConnectable()) { System.out.println("key is connnectable"); if (channel.isConnectionPending()) { channel.finishConnect(); } channel.register(selector, SelectionKey.OP_WRITE); } else if (key.isWritable()) { ByteBuffer block = encoder.encode(CharBuffer.wrap("GET / HTTP/1.1\r\nHost: www.iteye.com\r\n\r\n")); channel.write(block); channel.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { ByteBuffer clientBuffer = ByteBuffer.allocate(1024 * 10); int count = channel.read(clientBuffer); if (count > 0) { clientBuffer.flip(); CharBuffer charBuffer = decoder.decode(clientBuffer); System.out.println(charBuffer.toString()); } else { channel.close(); } } } public static void main(String[] args) throws Exception { NIODemo client = new NIODemo(); client.start(); client.fetch(); } 发现运行时总是阻塞在fetch方法中channel往selector注册处, client.register(selector, SelectionKey.OP_CONNECT); 如果main方法中先调用fetch()再调用start()则不会出现此问题 public static void main(String[] args) throws Exception { NIODemo client = new NIODemo(); client.fetch(); client.start(); } 请问为什么出现这种现象,多谢 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-09-20
最后修改:2010-09-21
仔细看了下api找到了答案,对于channel的register方法有如下说明:
引用 This method will then synchronize on the selector's key set and therefore may block if invoked concurrently with another registration or selection operation involving the same selector.
当第一次调用start方法时,selector阻塞在select方法上,此时再调用fetch(),根据上文api所说,此时channel的register(..)将阻塞直到selector.select()返回. 可以通过调用selector.wakeup()或者对阻塞在selector.select()处的thread调用interrupt方法使select()返回. |
|
返回顶楼 | |
发表时间:2010-09-21
路过,学习一下,这边基本都用mina,没深入了解过NIO
|
|
返回顶楼 | |
发表时间:2010-09-21
你connect事件都没注册怎么可能连接上。
|
|
返回顶楼 | |
发表时间:2010-09-21
我觉得,你这样写不属于nio client。nio的http client应该是一个客户端连续多发起http请求。然后根据之前注册的key,分别处理返回的请求数据。
|
|
返回顶楼 | |
发表时间:2010-09-21
最后修改:2010-09-21
xuganggogo 写道 我觉得,你这样写不属于nio client。nio的http client应该是一个客户端连续多发起http请求。然后根据之前注册的key,分别处理返回的请求数据。
其实我要做得client类似一个爬虫,不间断的往里面放入url,然后这个client负责把网页内容抓回来 NIODemo client = new NIODemo(); client.start(); client.fetch("http://xxx1"); client.fetch("http://xxx2"); client.fetch("http://xxx2"); |
|
返回顶楼 | |
发表时间:2010-09-21
最后修改:2010-09-21
在client.register(selector, SelectionKey.OP_CONNECT);前调用
selector.wakeup(); selector.select();阻塞了selector所在的线程。由于当前的keyset是空的没有事件唤醒它。 当register时需要同步selector中的key set 这么做也不能百分之百保证,如果selector.wakeup();后当前进程挂起,有切换到了 selector.select()还会被挂起,不过机率是相当的低。最好select()加一个超时时间 select(timeout) -------------------------------------------------------------- # public void fetch() throws IOException { # # SocketChannel client = SocketChannel.open(); # # client.configureBlocking(false); # # InetSocketAddress address = new InetSocketAddress("127.0.0.1", 80); # selector.wakeup(); # client.register(selector, SelectionKey.OP_CONNECT); # # client.connect(address); # } |
|
返回顶楼 | |