注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

客户端select的退出的机制  

2014-06-09 20:56:29|  分类: 网络服务编程技术 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

客户端select的退出的机制

在客户端使用select机制时,如果将超时的参数设置为NULL,表明会永远阻塞在这里,直到有事件句柄的通知为止。

但这里有一个问题,一般来说,这种情况都是在线程里进行操作的,如果通信一直保持连接则不会有什么问题,如果通信断掉,程序重新连接的时候儿,如果是每次主动创建一个连接类的情况下(如果只使用单独连接机制,则另外谈),线程的退出就是一个比较麻烦的问题。因为很大可能的情况,整个程序是不会退出,而只是连接的线程再次启动连接。

这次就恰好遇到了这个问题,select在遇到SOCKET句柄错误时,确实会产生一个返回值为-1的错误,但是,不知道为什么连续的反复CONNECT时候,CLOSE当前的SOCKET,却不会关闭线程,最大的可能是快速的创建连接,造成SOCKET的通信线程无法退出,从而导致过多的线程被创建出来。结果是不言而喻的,内存资源耗尽,引起内核转储的错误。

用一种方法来解决了这个问题,就是select的超时设置成2秒,然后在外面通知CLOSE时,最外面的WHILE的循环变量同时置为FALSE,同时将thread.detach改成了在析构函数中thread.join这样就会使程序在2秒后自动退出整个线程。经过测试以2秒钟一次连接服务端,2300多次没有出现任何问题,CPU和内存的占用率都非常的低。达到了目的。

这时候,主动把服务端关闭,结果客户端立刻崩溃报了如下一个错误:

terminate called after throwing an instance of 'std::system_error'   what():  Invalid argument

下断点调试了下,发现原因是在析构函数中JOIN时崩溃的。查看帮助:

exception type

error condition

description

system_error

errc::invalid_argument

- The thread object is not joinable

system_error

errc::no_such_process

- The thread object is not valid

system_error

errc::resource_deadlock_would_occur

- The current thread is the same as the thread attempted to join, or
- A deadlock was detected (implementations may detect certain cases of deadlock).

 

看第一个错误,细一想,果然是,因为服务端关闭,那么连接是无法成功的,那么就不会创建线程,那么线程的变量就是一个空值,空值默认是not joinable的,所以会在析构时直接挂掉。

在原来的程序中,创建线程都是可以直接判断返回值来判断是否创建成功,而这个C++11thread还真不知道如何判断其是成功的,后来经过查找资料发现了下面方法:

NetClientSelect::~NetClientSelect()

{

         if (_recvThread.get_id() != std::thread::id())

             _recvThread.join();

}

接收的核心代码:

         while (ncs->_isQuit)

         {

                   FD_SET(ncs->_socket,&socketSet);

                   struct timeval timeout;

                   timeout.tv_sec = 2;   //设置两秒

                   timeout.tv_usec = 0;

                   //timeval中的两个成员均为0则立刻返回,直接给一个NULL,则永远阻塞,直到某个描述符就绪

                   ready = select(maxFd + 1,&socketSet,NULL,NULL,&timeout);

                printf ("直接退出网络通信!\n");

……..

}

可见对不同的创建方法,控制的方法也会不同,回头有时间把只重连接的代码写出来。

 

 

 

  评论这张
 
阅读(603)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017