在linux环境下,遇到很怪的问题。
当客户端的socket关闭,正常程序关闭或者是客户端程序退出。
在服务端的selector还可以有事件被监听到,监听到的read事件,read为0,服务器端对应这个客户端的socket没有关闭,而且读不会有异常抛出。所以这样导致监听的线程空跑,cpu达到100%
不知道有没有同学解决过这样的问题的,怎么解决,高分谢谢。
43 个解决方案
#1
这具体要看代码了。
#2
当服务端得知客户端关闭了,服务端做了哪些处理?
#3
服务器端有对channel进行read的异常处理。
按照我的想法,如果客户端的socket关闭了,那么这里read的时候应该有异常抛出的。不过这里居然还是可以read,没有异常,不过read的字节是0.
按照我的想法,如果客户端的socket关闭了,那么这里read的时候应该有异常抛出的。不过这里居然还是可以read,没有异常,不过read的字节是0.
#4
代码我整理一下,帖上来,
帖服务器的代码就可以了吧。
帖服务器的代码就可以了吧。
#5
路过看看
#6
while(true)
{
try
{
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
if (keys.size()>0) {
for (SelectionKey key : keys)
{
if (key.isAcceptable())
{
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel sc = ssc.accept();
logger.info("Accept " + sc.socket());
sc.configureBlocking(false);
sc.socket().setReceiveBufferSize(4096);
//sc.socket().setSoLinger(true, 0);
//sc.socket().setSoTimeout(1000*60);
sc.register(selector, SelectionKey.OP_READ);
sessionMgr.createSession(sc);
}
else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ)
{
requestQueueManager.receiveRequest((SocketChannel) key.channel());
}
}
keys.clear();
}
}
catch (CancelledKeyException e) {
logger.debug("Key is cancelled.<"+e.getMessage()+">");
} catch (IOException e) {
logger.error("Process Error: ", e);
}
}
}
这是监听accept,并且注册read的代码,只是用了读事件,没有用异步写。
{
try
{
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
if (keys.size()>0) {
for (SelectionKey key : keys)
{
if (key.isAcceptable())
{
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel sc = ssc.accept();
logger.info("Accept " + sc.socket());
sc.configureBlocking(false);
sc.socket().setReceiveBufferSize(4096);
//sc.socket().setSoLinger(true, 0);
//sc.socket().setSoTimeout(1000*60);
sc.register(selector, SelectionKey.OP_READ);
sessionMgr.createSession(sc);
}
else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ)
{
requestQueueManager.receiveRequest((SocketChannel) key.channel());
}
}
keys.clear();
}
}
catch (CancelledKeyException e) {
logger.debug("Key is cancelled.<"+e.getMessage()+">");
} catch (IOException e) {
logger.error("Process Error: ", e);
}
}
}
这是监听accept,并且注册read的代码,只是用了读事件,没有用异步写。
#7
#8
requestQueueManager.receiveRequest((SocketChannel) key.channel());
是把有事件的channel push到一个link里。
然后在用一个processThreadPool对每个link里的channel进行处理。
while (runflag) {
if ((channel = requestQueueManager.pollRequestChannel()) != null) {
try
{
processRequest(channel);
}
catch (NullPointerException e1) {
logger.error("Read Data error: " + channel);
}
catch (Exception ex) {
logger.error("Read Data error: ", ex);
try
{
serverProcessor.beforeDiscard(channel);
}
catch (Exception e) {
// TODO: handle exception
logger.warn("before discard connection error. As " + e.getMessage());
}
sessionManager.closeSessionByChannel(channel);
}
}
else
{
try
{
TimeUnit.MILLISECONDS.sleep(100);
}
catch (InterruptedException e)
{
logger.warn("Sleep error. As " + e.getMessage());
}
}
}
是把有事件的channel push到一个link里。
然后在用一个processThreadPool对每个link里的channel进行处理。
while (runflag) {
if ((channel = requestQueueManager.pollRequestChannel()) != null) {
try
{
processRequest(channel);
}
catch (NullPointerException e1) {
logger.error("Read Data error: " + channel);
}
catch (Exception ex) {
logger.error("Read Data error: ", ex);
try
{
serverProcessor.beforeDiscard(channel);
}
catch (Exception e) {
// TODO: handle exception
logger.warn("before discard connection error. As " + e.getMessage());
}
sessionManager.closeSessionByChannel(channel);
}
}
else
{
try
{
TimeUnit.MILLISECONDS.sleep(100);
}
catch (InterruptedException e)
{
logger.warn("Sleep error. As " + e.getMessage());
}
}
}
#9
requestQueueManager.receiveRequest((SocketChannel) key.channel());
是把有事件的channel push到一个link里。
然后在用一个processThreadPool对每个link里的channel进行处理。
processRequest(channel);就是处理channel的地方,这里就是没有异常出来,而且channel看到的居然还是open的。
while (runflag) {
if (( channel = requestQueueManager.pollRequestChannel()) != null) {
try
{
processRequest(channel);
}
catch (NullPointerException e1) {
logger.error("Read Data error: " + channel);
}
catch (Exception ex) {
logger.error("Read Data error: ", ex);
try
{
serverProcessor.beforeDiscard(channel);
}
catch (Exception e) {
// TODO: handle exception
logger.warn("before discard connection error. As " + e.getMessage());
}
sessionManager.closeSessionByChannel(channel);
}
}
else
{
try
{
TimeUnit.MILLISECONDS.sleep(100);
}
catch (InterruptedException e)
{
logger.warn("Sleep error. As " + e.getMessage());
}
}
}
是把有事件的channel push到一个link里。
然后在用一个processThreadPool对每个link里的channel进行处理。
processRequest(channel);就是处理channel的地方,这里就是没有异常出来,而且channel看到的居然还是open的。
while (runflag) {
if (( channel = requestQueueManager.pollRequestChannel()) != null) {
try
{
processRequest(channel);
}
catch (NullPointerException e1) {
logger.error("Read Data error: " + channel);
}
catch (Exception ex) {
logger.error("Read Data error: ", ex);
try
{
serverProcessor.beforeDiscard(channel);
}
catch (Exception e) {
// TODO: handle exception
logger.warn("before discard connection error. As " + e.getMessage());
}
sessionManager.closeSessionByChannel(channel);
}
}
else
{
try
{
TimeUnit.MILLISECONDS.sleep(100);
}
catch (InterruptedException e)
{
logger.warn("Sleep error. As " + e.getMessage());
}
}
}
#10
看网上说有jdk的bug 可能导致cpu 100%,所以升级到了6u21,还是不行,。
#11
你看一下客户端关闭后,用 netstat 查看客户端、服务端上之前的通信端口是什么状态?
一般服务端用 read 读到 -1 时,就表示客户端关掉了,读到是 0 的话根据 API DOC 描述也是有可能的。是不是客户端关掉后,服务端一直读到 0?
如果服务端检查到客户端关闭的话,需要在 SelectionKey 上调用:
key.cancel();
key.channel().close();
这样来关闭服务端与客户端的套接字,我好像也没看到这样的代码。
一般服务端用 read 读到 -1 时,就表示客户端关掉了,读到是 0 的话根据 API DOC 描述也是有可能的。是不是客户端关掉后,服务端一直读到 0?
如果服务端检查到客户端关闭的话,需要在 SelectionKey 上调用:
key.cancel();
key.channel().close();
这样来关闭服务端与客户端的套接字,我好像也没看到这样的代码。
#12
这位 很n
#13
楼主,在C++ 上面也会有这样的情况.之前,我差过一些相关资料.发现好像是TCP/IP 协议的一个底层的Bug, 就是在某些情况下出现一些假的Socket 连接.
当时,我的解决方法就是对没一条Socket 增加心跳包的检测;若发现心跳包不能正常返回就认为这个Socket 连接时已经失效了. 这样一方面可以避免假连接的出现.另一方面,也可以主动去检查各个客户端连接上来的网络情况.若出现网络情况比较恶劣的,可以优先解决掉.不用让系统超时地等待.
当时,我的解决方法就是对没一条Socket 增加心跳包的检测;若发现心跳包不能正常返回就认为这个Socket 连接时已经失效了. 这样一方面可以避免假连接的出现.另一方面,也可以主动去检查各个客户端连接上来的网络情况.若出现网络情况比较恶劣的,可以优先解决掉.不用让系统超时地等待.
#14
Socket 没搞过
友情了
火龙果真是热情啊
友情了
火龙果真是热情啊
#15
就是一张读的都是0,客户端的程序都关闭了,
服务器的socket还能读得到,也不抛错,socket不能检查到关闭。所以无法去判断什么时候cancel
#16
有没有详细的对这个bug的描述呀。
我现在也是想到用heartbeat包来进行检查了。原来也有心跳的检查,不过服务器端只是发hb包,由客户端自己主动放弃,以前是直接用socket来做的,这次这个客户端在线的负载要求的比较大,所以才转着用nio的,现在还是poc,觉得其他的都不错,就是这个问题没有解决。
#17
客户端关闭以后,服务器端得socket都没有释放,lsof查看管道文件都没有释放,郁闷呀
#18
自己写的? 连接时消息都能收到? 客户端断开时就监听不到了?
#19
1 协议上没有明确讲述这个问题
2 不需要每时每刻监听,这样资源消耗肯定厉害.例如: 间隔30秒或者监听一次.
3 socket 是双向通道,只要有一方放弃;另一方就会自动断开.
2 不需要每时每刻监听,这样资源消耗肯定厉害.例如: 间隔30秒或者监听一次.
3 socket 是双向通道,只要有一方放弃;另一方就会自动断开.
#20
如果是这样的话,很可能客户端断开有问题。
#21
不懂 帮顶
#22
#23
非常谢谢,。
#24
客户端需要怎么断开哟。测试的客户端是用socket。close关闭的。也试过直接异常关闭程序。也就是ctrl+c都出现上面的问题。此时客户端的socket是关闭的。
#25
#26
good habit
#27
一起用nio做客户端做压力测试,有过
select空跑的情况。
也就是
while(true)
{
try
{
selector.select();
....
}
.....
}
也就是select取到事件,但是select()的返回是0,信任这个0,所以用这个返回做判断,造成select这里不停的空跑,不知道有没有兄弟也越到过这个问题,后来修改成最上面的代码,虽然比较恶心,但是还是解决了这个问题。 不知道mina里有没有这样的问题。有没有XDJM是用mina的有没有越到类似的问题。
select空跑的情况。
也就是
while(true)
{
try
{
selector.select();
....
}
.....
}
也就是select取到事件,但是select()的返回是0,信任这个0,所以用这个返回做判断,造成select这里不停的空跑,不知道有没有兄弟也越到过这个问题,后来修改成最上面的代码,虽然比较恶心,但是还是解决了这个问题。 不知道mina里有没有这样的问题。有没有XDJM是用mina的有没有越到类似的问题。
#28
顶一下,做个标记,顺便获得每日10分可用分。
#29
学习学习
#30
#31
#32
客户端启动后,找到对应的连接端口号,在客户端关闭后,再用 netstat 看一下那个端口的状态
#33
我也没碰到过这么奇怪的问题呢。
看了一下 SocketChannel 实现的源代码,SocketChannel#read 在 SocketChannel#isOpen 返回 false 的情况下会直接返回 0。所以看一下 SocketChannel#isOpen 方法返回的是什么。
看了一下 SocketChannel 实现的源代码,SocketChannel#read 在 SocketChannel#isOpen 返回 false 的情况下会直接返回 0。所以看一下 SocketChannel#isOpen 方法返回的是什么。
#34
在linux下用lsof查看client和server
client程序关闭后 该pipe handle都没有,但是server端还有,没有释放。
#35
哦,这样啊。
我一般查看端口状态的,呵呵。
我一般查看端口状态的,呵呵。
#36
差不多的功能。表现的形式不一样而已。
嘻嘻嘻。
#37
isOpen返回是true呀。
#38
1 程序问题是经常出现,而且是很频繁. 如果是出现的几率很高,我可以肯定答复你: Sorry , 我引导你到了一个错误的方向. 因为 TCP/IP 不会经常出现 "假连接";只有在一些网络环境极为恶劣的情况下出现.例如: 交换机或者路由器之间的网络切换,网络攻击等等..
2 在Java 具体实现上我是初哥,在多线程方面暂时都是迷迷糊糊的.就不多讲了.继续关注下.
2 在Java 具体实现上我是初哥,在多线程方面暂时都是迷迷糊糊的.就不多讲了.继续关注下.
#39
别这么客气
刚才看了看在服务器上的和客户端的socket的状态是CLOSE_WAIT
客户机的socket已经没有了。
这样情况下从channel里读取没有异常,所以就没法进行异常的处理,关闭socket。
刚才看了看在服务器上的和客户端的socket的状态是CLOSE_WAIT
客户机的socket已经没有了。
这样情况下从channel里读取没有异常,所以就没法进行异常的处理,关闭socket。
#40
太怪异了。先用hb回给的方式来试试了,主要看性能能不能行了。
给贴了,
谢谢这里帮助的XDJM们,特别是火龙果和(Mark Liang)叻。
以后有问题,再开新贴。
给贴了,
谢谢这里帮助的XDJM们,特别是火龙果和(Mark Liang)叻。
以后有问题,再开新贴。
#41
你分给错了吧!!
#42
你这个问题最后是怎么解决的?我也遇到一样的问题
#43
5月份的帖子,不知道你解决问题没, 以前我也遇到过read到0的事件, select的时候每次都返回一个read事件, 经检查,原来是ByteBuffer 复用照成的问题, 每次read时建议clear buffer, (如果buffer flip过,那么就会返回0,如果buffer读满了,照样会返回0, 在read到0的情况我们是不会关闭SelectionKey的,所以照成死循环)。 在nio方面java还是存在很多bug的。 在1.6u4以后貌似解决了。
#1
这具体要看代码了。
#2
当服务端得知客户端关闭了,服务端做了哪些处理?
#3
服务器端有对channel进行read的异常处理。
按照我的想法,如果客户端的socket关闭了,那么这里read的时候应该有异常抛出的。不过这里居然还是可以read,没有异常,不过read的字节是0.
按照我的想法,如果客户端的socket关闭了,那么这里read的时候应该有异常抛出的。不过这里居然还是可以read,没有异常,不过read的字节是0.
#4
代码我整理一下,帖上来,
帖服务器的代码就可以了吧。
帖服务器的代码就可以了吧。
#5
路过看看
#6
while(true)
{
try
{
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
if (keys.size()>0) {
for (SelectionKey key : keys)
{
if (key.isAcceptable())
{
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel sc = ssc.accept();
logger.info("Accept " + sc.socket());
sc.configureBlocking(false);
sc.socket().setReceiveBufferSize(4096);
//sc.socket().setSoLinger(true, 0);
//sc.socket().setSoTimeout(1000*60);
sc.register(selector, SelectionKey.OP_READ);
sessionMgr.createSession(sc);
}
else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ)
{
requestQueueManager.receiveRequest((SocketChannel) key.channel());
}
}
keys.clear();
}
}
catch (CancelledKeyException e) {
logger.debug("Key is cancelled.<"+e.getMessage()+">");
} catch (IOException e) {
logger.error("Process Error: ", e);
}
}
}
这是监听accept,并且注册read的代码,只是用了读事件,没有用异步写。
{
try
{
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
if (keys.size()>0) {
for (SelectionKey key : keys)
{
if (key.isAcceptable())
{
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel sc = ssc.accept();
logger.info("Accept " + sc.socket());
sc.configureBlocking(false);
sc.socket().setReceiveBufferSize(4096);
//sc.socket().setSoLinger(true, 0);
//sc.socket().setSoTimeout(1000*60);
sc.register(selector, SelectionKey.OP_READ);
sessionMgr.createSession(sc);
}
else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ)
{
requestQueueManager.receiveRequest((SocketChannel) key.channel());
}
}
keys.clear();
}
}
catch (CancelledKeyException e) {
logger.debug("Key is cancelled.<"+e.getMessage()+">");
} catch (IOException e) {
logger.error("Process Error: ", e);
}
}
}
这是监听accept,并且注册read的代码,只是用了读事件,没有用异步写。
#7
#8
requestQueueManager.receiveRequest((SocketChannel) key.channel());
是把有事件的channel push到一个link里。
然后在用一个processThreadPool对每个link里的channel进行处理。
while (runflag) {
if ((channel = requestQueueManager.pollRequestChannel()) != null) {
try
{
processRequest(channel);
}
catch (NullPointerException e1) {
logger.error("Read Data error: " + channel);
}
catch (Exception ex) {
logger.error("Read Data error: ", ex);
try
{
serverProcessor.beforeDiscard(channel);
}
catch (Exception e) {
// TODO: handle exception
logger.warn("before discard connection error. As " + e.getMessage());
}
sessionManager.closeSessionByChannel(channel);
}
}
else
{
try
{
TimeUnit.MILLISECONDS.sleep(100);
}
catch (InterruptedException e)
{
logger.warn("Sleep error. As " + e.getMessage());
}
}
}
是把有事件的channel push到一个link里。
然后在用一个processThreadPool对每个link里的channel进行处理。
while (runflag) {
if ((channel = requestQueueManager.pollRequestChannel()) != null) {
try
{
processRequest(channel);
}
catch (NullPointerException e1) {
logger.error("Read Data error: " + channel);
}
catch (Exception ex) {
logger.error("Read Data error: ", ex);
try
{
serverProcessor.beforeDiscard(channel);
}
catch (Exception e) {
// TODO: handle exception
logger.warn("before discard connection error. As " + e.getMessage());
}
sessionManager.closeSessionByChannel(channel);
}
}
else
{
try
{
TimeUnit.MILLISECONDS.sleep(100);
}
catch (InterruptedException e)
{
logger.warn("Sleep error. As " + e.getMessage());
}
}
}
#9
requestQueueManager.receiveRequest((SocketChannel) key.channel());
是把有事件的channel push到一个link里。
然后在用一个processThreadPool对每个link里的channel进行处理。
processRequest(channel);就是处理channel的地方,这里就是没有异常出来,而且channel看到的居然还是open的。
while (runflag) {
if (( channel = requestQueueManager.pollRequestChannel()) != null) {
try
{
processRequest(channel);
}
catch (NullPointerException e1) {
logger.error("Read Data error: " + channel);
}
catch (Exception ex) {
logger.error("Read Data error: ", ex);
try
{
serverProcessor.beforeDiscard(channel);
}
catch (Exception e) {
// TODO: handle exception
logger.warn("before discard connection error. As " + e.getMessage());
}
sessionManager.closeSessionByChannel(channel);
}
}
else
{
try
{
TimeUnit.MILLISECONDS.sleep(100);
}
catch (InterruptedException e)
{
logger.warn("Sleep error. As " + e.getMessage());
}
}
}
是把有事件的channel push到一个link里。
然后在用一个processThreadPool对每个link里的channel进行处理。
processRequest(channel);就是处理channel的地方,这里就是没有异常出来,而且channel看到的居然还是open的。
while (runflag) {
if (( channel = requestQueueManager.pollRequestChannel()) != null) {
try
{
processRequest(channel);
}
catch (NullPointerException e1) {
logger.error("Read Data error: " + channel);
}
catch (Exception ex) {
logger.error("Read Data error: ", ex);
try
{
serverProcessor.beforeDiscard(channel);
}
catch (Exception e) {
// TODO: handle exception
logger.warn("before discard connection error. As " + e.getMessage());
}
sessionManager.closeSessionByChannel(channel);
}
}
else
{
try
{
TimeUnit.MILLISECONDS.sleep(100);
}
catch (InterruptedException e)
{
logger.warn("Sleep error. As " + e.getMessage());
}
}
}
#10
看网上说有jdk的bug 可能导致cpu 100%,所以升级到了6u21,还是不行,。
#11
你看一下客户端关闭后,用 netstat 查看客户端、服务端上之前的通信端口是什么状态?
一般服务端用 read 读到 -1 时,就表示客户端关掉了,读到是 0 的话根据 API DOC 描述也是有可能的。是不是客户端关掉后,服务端一直读到 0?
如果服务端检查到客户端关闭的话,需要在 SelectionKey 上调用:
key.cancel();
key.channel().close();
这样来关闭服务端与客户端的套接字,我好像也没看到这样的代码。
一般服务端用 read 读到 -1 时,就表示客户端关掉了,读到是 0 的话根据 API DOC 描述也是有可能的。是不是客户端关掉后,服务端一直读到 0?
如果服务端检查到客户端关闭的话,需要在 SelectionKey 上调用:
key.cancel();
key.channel().close();
这样来关闭服务端与客户端的套接字,我好像也没看到这样的代码。
#12
这位 很n
#13
楼主,在C++ 上面也会有这样的情况.之前,我差过一些相关资料.发现好像是TCP/IP 协议的一个底层的Bug, 就是在某些情况下出现一些假的Socket 连接.
当时,我的解决方法就是对没一条Socket 增加心跳包的检测;若发现心跳包不能正常返回就认为这个Socket 连接时已经失效了. 这样一方面可以避免假连接的出现.另一方面,也可以主动去检查各个客户端连接上来的网络情况.若出现网络情况比较恶劣的,可以优先解决掉.不用让系统超时地等待.
当时,我的解决方法就是对没一条Socket 增加心跳包的检测;若发现心跳包不能正常返回就认为这个Socket 连接时已经失效了. 这样一方面可以避免假连接的出现.另一方面,也可以主动去检查各个客户端连接上来的网络情况.若出现网络情况比较恶劣的,可以优先解决掉.不用让系统超时地等待.
#14
Socket 没搞过
友情了
火龙果真是热情啊
友情了
火龙果真是热情啊
#15
就是一张读的都是0,客户端的程序都关闭了,
服务器的socket还能读得到,也不抛错,socket不能检查到关闭。所以无法去判断什么时候cancel
#16
有没有详细的对这个bug的描述呀。
我现在也是想到用heartbeat包来进行检查了。原来也有心跳的检查,不过服务器端只是发hb包,由客户端自己主动放弃,以前是直接用socket来做的,这次这个客户端在线的负载要求的比较大,所以才转着用nio的,现在还是poc,觉得其他的都不错,就是这个问题没有解决。
#17
客户端关闭以后,服务器端得socket都没有释放,lsof查看管道文件都没有释放,郁闷呀
#18
自己写的? 连接时消息都能收到? 客户端断开时就监听不到了?
#19
1 协议上没有明确讲述这个问题
2 不需要每时每刻监听,这样资源消耗肯定厉害.例如: 间隔30秒或者监听一次.
3 socket 是双向通道,只要有一方放弃;另一方就会自动断开.
2 不需要每时每刻监听,这样资源消耗肯定厉害.例如: 间隔30秒或者监听一次.
3 socket 是双向通道,只要有一方放弃;另一方就会自动断开.
#20
如果是这样的话,很可能客户端断开有问题。
#21
不懂 帮顶
#22
#23
非常谢谢,。
#24
客户端需要怎么断开哟。测试的客户端是用socket。close关闭的。也试过直接异常关闭程序。也就是ctrl+c都出现上面的问题。此时客户端的socket是关闭的。
#25
#26
good habit
#27
一起用nio做客户端做压力测试,有过
select空跑的情况。
也就是
while(true)
{
try
{
selector.select();
....
}
.....
}
也就是select取到事件,但是select()的返回是0,信任这个0,所以用这个返回做判断,造成select这里不停的空跑,不知道有没有兄弟也越到过这个问题,后来修改成最上面的代码,虽然比较恶心,但是还是解决了这个问题。 不知道mina里有没有这样的问题。有没有XDJM是用mina的有没有越到类似的问题。
select空跑的情况。
也就是
while(true)
{
try
{
selector.select();
....
}
.....
}
也就是select取到事件,但是select()的返回是0,信任这个0,所以用这个返回做判断,造成select这里不停的空跑,不知道有没有兄弟也越到过这个问题,后来修改成最上面的代码,虽然比较恶心,但是还是解决了这个问题。 不知道mina里有没有这样的问题。有没有XDJM是用mina的有没有越到类似的问题。
#28
顶一下,做个标记,顺便获得每日10分可用分。
#29
学习学习
#30
#31
#32
客户端启动后,找到对应的连接端口号,在客户端关闭后,再用 netstat 看一下那个端口的状态
#33
我也没碰到过这么奇怪的问题呢。
看了一下 SocketChannel 实现的源代码,SocketChannel#read 在 SocketChannel#isOpen 返回 false 的情况下会直接返回 0。所以看一下 SocketChannel#isOpen 方法返回的是什么。
看了一下 SocketChannel 实现的源代码,SocketChannel#read 在 SocketChannel#isOpen 返回 false 的情况下会直接返回 0。所以看一下 SocketChannel#isOpen 方法返回的是什么。
#34
在linux下用lsof查看client和server
client程序关闭后 该pipe handle都没有,但是server端还有,没有释放。
#35
哦,这样啊。
我一般查看端口状态的,呵呵。
我一般查看端口状态的,呵呵。
#36
差不多的功能。表现的形式不一样而已。
嘻嘻嘻。
#37
isOpen返回是true呀。
#38
1 程序问题是经常出现,而且是很频繁. 如果是出现的几率很高,我可以肯定答复你: Sorry , 我引导你到了一个错误的方向. 因为 TCP/IP 不会经常出现 "假连接";只有在一些网络环境极为恶劣的情况下出现.例如: 交换机或者路由器之间的网络切换,网络攻击等等..
2 在Java 具体实现上我是初哥,在多线程方面暂时都是迷迷糊糊的.就不多讲了.继续关注下.
2 在Java 具体实现上我是初哥,在多线程方面暂时都是迷迷糊糊的.就不多讲了.继续关注下.
#39
别这么客气
刚才看了看在服务器上的和客户端的socket的状态是CLOSE_WAIT
客户机的socket已经没有了。
这样情况下从channel里读取没有异常,所以就没法进行异常的处理,关闭socket。
刚才看了看在服务器上的和客户端的socket的状态是CLOSE_WAIT
客户机的socket已经没有了。
这样情况下从channel里读取没有异常,所以就没法进行异常的处理,关闭socket。
#40
太怪异了。先用hb回给的方式来试试了,主要看性能能不能行了。
给贴了,
谢谢这里帮助的XDJM们,特别是火龙果和(Mark Liang)叻。
以后有问题,再开新贴。
给贴了,
谢谢这里帮助的XDJM们,特别是火龙果和(Mark Liang)叻。
以后有问题,再开新贴。
#41
你分给错了吧!!
#42
你这个问题最后是怎么解决的?我也遇到一样的问题
#43
5月份的帖子,不知道你解决问题没, 以前我也遇到过read到0的事件, select的时候每次都返回一个read事件, 经检查,原来是ByteBuffer 复用照成的问题, 每次read时建议clear buffer, (如果buffer flip过,那么就会返回0,如果buffer读满了,照样会返回0, 在read到0的情况我们是不会关闭SelectionKey的,所以照成死循环)。 在nio方面java还是存在很多bug的。 在1.6u4以后貌似解决了。