问题描述如下:
鄙人在写nio简单例子的时候出现了很奇怪的问题,服务器端部分代码如下:
while (selector.select() > 0)
{
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator it = readyKeys.iterator();
System.out.println("while out");
while (it.hasNext())
{
System.out.println("while in");
SelectionKey key = (SelectionKey) it.next();
it.remove();
if (key.isAcceptable())
{
System.out.println("Key is Acceptable");
socket = (SocketChannel) ssc.accept();
socket.configureBlocking(false);
socket.register(selector,SelectionKey.OP_READ|SelectionKey.OP_WRITE);
}
if (key.isReadable()) {
System.out.println("Key is readable");
socket = (SocketChannel) key.channel();
ByteBuffer buf = ByteBuffer.allocate(25);
buf.clear();
socket.read(buf);
buf.flip();
Charset charset = Charset.forName("us-ascii");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buf);
String result = charBuffer.toString();
System.out.println("Receive Data:" + result);
key.cancel();//如果这个注释的话,就会进行无限循环
}
}客户端代码:public static int sendMessage(SocketChannel client) {
String msg = null;
ByteBuffer bytebuf=ByteBuffer.allocate(1024);
int nBytes = 0;
try {
msg = "It's message from client!";
System.out.println("msg is "+msg);
bytebuf.clear();
bytebuf.put(msg.getBytes());
bytebuf.flip();
nBytes = client.write(bytebuf);
System.out.println("It's message from client!".getBytes().length);
client.close(); } catch (IOException e) {
e.printStackTrace();
}
return nBytes;
}客户端和服务器端的部分代码就是上面的,客户端发送数据给服务器端,服务器按道理执行了
SelectionKey key = (SelectionKey) it.next();
it.remove();的代码之后注销了该键,如果执行完读操作之后,只要加上key.cancel()之后才可以正常读取一条数据。it.remove()之后为什么selector.select() > 0依然成立,运行代码的打印结果:
while out
while in
Key is readable
Receive Data:
while out
while in
Key is readable
Receive Data:
while out
while in
Key is readable
Receive Data:。。
求高手解答。
鄙人在写nio简单例子的时候出现了很奇怪的问题,服务器端部分代码如下:
while (selector.select() > 0)
{
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator it = readyKeys.iterator();
System.out.println("while out");
while (it.hasNext())
{
System.out.println("while in");
SelectionKey key = (SelectionKey) it.next();
it.remove();
if (key.isAcceptable())
{
System.out.println("Key is Acceptable");
socket = (SocketChannel) ssc.accept();
socket.configureBlocking(false);
socket.register(selector,SelectionKey.OP_READ|SelectionKey.OP_WRITE);
}
if (key.isReadable()) {
System.out.println("Key is readable");
socket = (SocketChannel) key.channel();
ByteBuffer buf = ByteBuffer.allocate(25);
buf.clear();
socket.read(buf);
buf.flip();
Charset charset = Charset.forName("us-ascii");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buf);
String result = charBuffer.toString();
System.out.println("Receive Data:" + result);
key.cancel();//如果这个注释的话,就会进行无限循环
}
}客户端代码:public static int sendMessage(SocketChannel client) {
String msg = null;
ByteBuffer bytebuf=ByteBuffer.allocate(1024);
int nBytes = 0;
try {
msg = "It's message from client!";
System.out.println("msg is "+msg);
bytebuf.clear();
bytebuf.put(msg.getBytes());
bytebuf.flip();
nBytes = client.write(bytebuf);
System.out.println("It's message from client!".getBytes().length);
client.close(); } catch (IOException e) {
e.printStackTrace();
}
return nBytes;
}客户端和服务器端的部分代码就是上面的,客户端发送数据给服务器端,服务器按道理执行了
SelectionKey key = (SelectionKey) it.next();
it.remove();的代码之后注销了该键,如果执行完读操作之后,只要加上key.cancel()之后才可以正常读取一条数据。it.remove()之后为什么selector.select() > 0依然成立,运行代码的打印结果:
while out
while in
Key is readable
Receive Data:
while out
while in
Key is readable
Receive Data:
while out
while in
Key is readable
Receive Data:。。
求高手解答。
解决方案 »
- java.util.TreeSet 可以放入重复的元素?
- 怎么终止我的这个线程
- 百度的一个算法面试题
- Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
- if(rs2.next()==false)这句有错误吗。。为什么if里面的代码执行不了。。rs2没有查询到结果
- 看JAVA学习笔记遇到的问题
- 用java制作浏览器
- 在Jbuilder9中用jdk1.5.0出现版本不对
- 菜鸟求救~~~~~~~!关于set path命令的问题????
- 【急求求帮助】整合Spring+Hibernate的时候出现Unrooted Tests求好人帮忙解决下!谢谢了!
- x=(y<x++)?1:0
- 如何监听JPasswordField是否成被点击?
楼主的socket.read(buf);一直返回-1,你没有进行判断处理,加上这个判断就不会死循环了。int length = socket.read(buf);
if(length == -1){
System.out.println("读到流末尾,说明客户端断开连接了。");
key.cancel();
key.channel().close();
break;
}
将管道关闭的前提是,另一方已经主动断开连接了。
楼主你的代码客户端发生数据后,调用 client.close(); 把socket给关闭了。
所以服务端那边在读数据的时候,如果判断为-1,说明你客户端都主动断开连接了,那么自然需要把监听取消和管道关闭了。你前面的问题就是因为没有做这个判断,所以才会陷入一个死循环一直在读数据。
public abstract void cancel()
使SelectionKey对象失效。
该方法把SelectionKey对象加入到与它关联的Selector对象的cancelled-keys集合中。当程序下一次执行Selector的select()方法时,该方法会把SelectionKey对象从3个集合中删除。
每次向选择器注册通道时就会创建一个选择键。通过调用某个键的 cancel 方法、关闭其通道,或者通过关闭其选择器来取消 该键之前,它一直保持有效。取消某个键不会立即从其选择器中移除它;相反,会将该键添加到选择器的已取消键集,以便在下一次进行选择操作时移除它。可通过调用某个键的 isValid 方法来测试其有效性。