NIO的奇怪事件 非常奇怪! 救救我!_!

04-04-17 sunkdjxiao
下面一个客户端代码(NioClient)一个服务器端代码(NioServer)

先运行NioServer 再运行NioClient 第一次正常 但隐藏着3个奇怪的地方:

1:

一关闭NioClient(NioServer还开着), NioServer又会发现一个SelectionKey.OP_READ事件,就是原先那个处理过的事件,都不知道为什么?

2:

一关闭NioServer(NioClient还开着),NioClient又会发现无数个SelectionKey.OP_READ事件(永远不会停止),都是原先那个处理过的事件,又都不知道为什么?

3:

关闭所有的重新开始;先开一个NioServer和一个NioClient(都不要关掉),再开个NioClient,这时第二个开的NioClient会发现无数个SelectionKey.OP_READ事件(永远不会停止),也都是原先那个处理过的事件,又又都不知道为什么?

气炸了 希望高手指点 超谢

import java.io.*;

import java.util.*;

import java.net.*;

import java.nio.*;

import java.nio.charset.*;

import java.nio.channels.*;

public class NioServer

{

Charset charset=Charset.forName("gbk");

CharsetDecoder decoder=charset.newDecoder();

CharsetEncoder encoder=charset.newEncoder();

Selector selector;

ServerSocketChannel server;

ByteBuffer bBuffer=ByteBuffer.allocate(1024);

CharBuffer cBuffer=CharBuffer.allocate(1024);

public NioServer(int port)

{

try

{

selector=Selector.open();

server = ServerSocketChannel.open();

server.configureBlocking(false);

InetSocketAddress isa=new InetSocketAddress(

InetAddress.getLocalHost(),port);

server.socket().bind(isa);

server.register(selector,SelectionKey.OP_ACCEPT);

System.out.println("服务器启动!");

service();

}

catch(IOException e)

{

System.out.println(e);

}

}

public void service()throws IOException

{

while(true)

{

if(selector.select()<=0)

continue;

Set readyKeys=selector.selectedKeys();

Iterator i=readyKeys.iterator();

while(i.hasNext())

{

SelectionKey key=(SelectionKey)i.next();

i.remove();

if(key.isAcceptable())

{

System.out.println("isAcceptable()");

ServerSocketChannel keyChannel=(ServerSocketChannel)

key.channel();

SocketChannel sc=(SocketChannel)keyChannel.accept();

sc.configureBlocking(false);

sc.register(selector,SelectionKey.OP_READ);

}

else if(key.isReadable())

{

System.out.println("isReadable()");

SocketChannel keyChannel=(SocketChannel)key.channel();

keyChannel.read(bBuffer);

bBuffer.flip();

decoder.decode(bBuffer, cBuffer, false);

cBuffer.flip();

System.out.println("客户端:"+cBuffer+"服务器端:响应!");

String s="响应!";

keyChannel.write(encoder.encode(cBuffer.wrap(s)));

}

else if(key.isConnectable())

{

System.out.println("isConnectable()");

}

else if(key.isWritable())

{

System.out.println("isWritable()");

}

else if(key.isValid())

{

System.out.println("key.isValid()");

}

}

}

}

public static void main(String sun[])

{

new NioServer(10000);

}

}

import java.io.*;

import java.util.*;

import java.net.*;

import java.nio.*;

import java.nio.charset.*;

import java.nio.channels.*;

public class NioClient

{

Charset charset=Charset.forName("gbk");

CharsetDecoder decoder=charset.newDecoder();

CharsetEncoder encoder=charset.newEncoder();

Selector selector;

SocketChannel client;

ByteBuffer bBuffer=ByteBuffer.allocate(1024);

CharBuffer cBuffer=CharBuffer.allocate(1024);

public NioClient(int port)

{

try

{

selector=Selector.open();

InetSocketAddress isa=new InetSocketAddress(

InetAddress.getLocalHost(),port);

client=SocketChannel.open();

client.configureBlocking(false);

client.connect(isa);

client.register(selector,SelectionKey.OP_CONNECT |

SelectionKey.OP_READ);

System.out.println("客户端启动!");

service();

}

catch(IOException e)

{

System.out.println(e);

}

}

public void service()throws IOException

{

while(true)

{

if(selector.select()<=0)

continue;

Set readyKeys=selector.selectedKeys();

System.out.println("事件:"+readyKeys.size());

Iterator i=readyKeys.iterator();

while(i.hasNext())

{

SelectionKey key=(SelectionKey)i.next();

i.remove();

if(key.isAcceptable())

{

System.out.println("isAcceptable()");

}

else if(key.isReadable())

{

System.out.println("isReadable()");

SocketChannel keyChannel=(SocketChannel)key.channel();

keyChannel.read(bBuffer);

bBuffer.flip();

decoder.decode(bBuffer, cBuffer, false);

cBuffer.flip();

System.out.println(cBuffer);

}

else if(key.isConnectable())

{

System.out.println("isConnectable()");

SocketChannel keyChannel=(SocketChannel)key.channel();

if(keyChannel.isConnectionPending())

keyChannel.finishConnect();

String s="请求!";

keyChannel.write(encoder.encode(cBuffer.wrap(s)));

}

else if(key.isWritable())

{

System.out.println("isWritable()");

}

else if(key.isValid())

{

System.out.println("key.isValid()");

}

}

}

}

public static void main(String sun[])

{

new NioClient(10000);

}

}

agilejava
2004-04-19 12:55
昨天和同事研究了一下,经过他的提醒明白了一些道理,你先加上这个试试。

bBuffer.clear(); //加上试试

cBuffer.clear(); //加上试试

System.out.println("isReadable()");

SocketChannel keyChannel=(SocketChannel)key.channel();

keyChannel.read(bBuffer);

bBuffer.flip();

decoder.decode(bBuffer, cBuffer, false);

cBuffer.flip();

多说一句,jdon最近很不稳定,老是有NullPointerException,板桥,你就不能解决一下啊,我开始怀疑你那书的质量了:)(开玩笑的)

banq
2004-04-22 11:52
to agilejava

你回答得有道理。

关于jdon论坛18到19日一些问题,是由于数据库服务器问题,网管给数据库服务器增加了防简单DDOS攻击的IPtables策略,但是影响了正常的访问,所以,访问量增加,就无法连接数据库服务器。

agilejava
2004-04-22 17:26
这得归功于我的同事,没有他的提示我是不会明白的:)

数据库的问题应该提示一下啊,要不很容易让人以为是程序有问题的,NPE是最让人头痛的问题了,应该怎么做我想不用我这个小程序员告诉你了吧:)

还得多说一句,你的书我同事已经买了,感觉很实用,我大体看了一下,不错:)

popcorny
2004-04-23 10:29
当connection断线时

都会有OP_READ的event产生

这时候read会回传-1

此时你可以呼叫channel.close();

去关闭这个connection

会这样的设计的原因是

让你的application可以知道一个channel断线的讯息

所以你没有执行close

则OP_READ的event就会一直发生

猜你喜欢
3Go 1 2 3 下一页