使用SocketChannel可以在非阻塞模式下进行读写,每次读取缓存的分配空间,然后等待下一次的读取。我的问题是,假设在某一次server发送的tcp流中,我必须进行两次读写。即第一次读取该流的一部分,剩下的等到下一次再读(区分标记是有一行为空,即读到空行时结束)。这个在代码中应该怎么控制呢?
我知道一种办法就是一次全读进来,然后按自己需求分成两部分,后半部分和下次读进行合并。因为这前半部分和后半部分的处理逻辑不一样(代码中,是解析前半部分的要求然后为后半部分开启线程新建http连接,所以传递起来比较费事)。
SocketChannel对应的socket可以获得InputStream,进而可以获得BufferefReader,进而可以精确读取行。因为程序依赖于Selector.select()查询。所以在把SocketChannel切换为Blocking模式,获得对应socket进行读写一次后,还要将其恢复为non-Blocking模式。具体代码如下:
if (selector.select(getTimeout()) != 0) { Iterator<SelectionKey> it = selector.selectedKeys() .iterator(); while (it.hasNext()) { SelectionKey key = it.next(); it.remove(); if (key.isReadable()) { if (key.equals(proxykey)) { SocketChannel channel = (SocketChannel) key .channel(); channel.configureBlocking(true); InputStream ins = Channels .newInputStream(channel); InputStreamReader is = new InputStreamReader( ins, "utf-8"); BufferedReader in = new BufferedReader(is); String res = in.readLine(); while (!res.equals("")) { System.out.println("========" + res); res = in.readLine(); } channel.configureBlocking(false); } } } }
方法理论上应该是可以的,但是我实现的有问题,请教大家问题出在哪里,或者进行精确读取的方法
这个问题解决了吗?
我也遇到了同样的问题.....
######这个问题解决了吗?
我也遇到了同样的问题.....
后来就是这样做了,在上面将channel设置为阻塞模式之前,先要取消其对应的SelectionKey:
key.cancel();
selector.selectNow();
在阻塞模式下处理完后,channel重新注册到selector:
channel.configureBlocking(false);
channel.register(selector,SelectionKey.OP_READ);
如果你有一些参数需要带着的话,可以看一下key.attach()方法
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。