我正在使用套接字制作多线程c ++应用程序 换句话说,我有很多要关闭的对象(例如我的服务器套接字,关闭我的线程等)。
我通常从main()函数的末尾关闭所有内容但是当我的app用户按 Ctrl + C <时,我无法以合适的方式关闭所有内容/ p>
顺便说一下,我可以将我的所有实例都保存为static
并关闭它们在静态函数中处理SIGINT
信号,但这对我来说听起来不太合适,因为我有很多实例靠近..
我准备用sigaction或signal捕获我的所有实例,但它无法编译。
signal(SIGINT, [myInstance](int) { myInstance.close() };
确实,向匿名函数添加一个实例捕获更改签名并使其不再是函数..
还有其他合适的方式来做我正在寻找的事情吗?
答案 0 :(得分:1)
使用事件驱动核心编写程序。
这个事件驱动的核心通常花费时间无所事事,等待新事件。
当您收到SIGINT时,只需与该事件驱动的核心通信即信号已到达。然后让它干净地关闭并退出主。
答案 1 :(得分:1)
我假设您使用的是Linux(或其他POSIX系统)。
然后仔细阅读signal(7)和signal-safety(7)和pthreads(7)(在Linux C ++ 11上std::thread
- s在pthreads上实现)。另请阅读POSIX signal concepts和一些Pthread tutorial。
请注意,信号和线程不能很好地协同工作。
一个众所周知的技巧是在初始化时设置一些pipe(7)(自我),并在该管道上设置信号处理程序write(2),然后让你的event loop处理管道输入和poll(2) - 它。即使Qt在Calling Qt Functions From Unix Signal Handlers页面中也建议并解释了这一点。
您可能想要使用sigaction(2)(而非signal(2))并且需要提供原始函数(不是std::function
或lambda表达式) - 最好是extern "C"
一个(以确保编译器正在为您的信号处理程序使用C调用约定。)
您可以考虑(针对SIGINT
&amp; SIGTERM
)使用特定于Linux的signalfd(2)。
您可能更愿意避免处理信号并使用其他inter-process communication工具(可能JSONRPC以上socket(7),或者HTTP使用某些HTTP服务器库,如{{ 3}}或libonion并使您的申请成为Wt),让您的程序轻轻终止。
答案 2 :(得分:0)
首先,看看boost :: asio,如果你还没有。这是一个很棒的图书馆,使网络变得更加容易。 至于你的问题:面向对象的设计可能对你有很大的帮助。不要直接使用套接字API。但是,如果没有任何更具体的信息(示例,片段)您的应用程序或您的背景,很难推荐任何具体的。以下是一些想法:
捕获SIGINT然后终止应用程序与主函数中等待按键的while循环没有多大区别。这只是结束应用程序的另一种方式。
编写服务器类。写一个连接类。在堆上实例化新连接并使用shared_ptr(使用make_shared)。保留活动连接对象的列表。为服务器类编写一个shutdown方法,迭代这些对象并关闭它们。在main中为每个侦听套接字实例化一个服务器对象(这样您就可以轻松拥有双栈应用程序,在IP4套接字上侦听IP4和另一个)。每个服务器都有一个单独的线程,每个连接都有一个线程(警告:当你同时有数百或数千个活动连接时这很慢)。
研究boost :: asio示例。有一些很好的例子可以做你想要的。另外,boost :: asio可以作为一个&#34;事件驱动的核心&#34;,正如另一个答案正确建议的那样。
尽可能使用RAII(资源获取是初始化)。
当您捕获SIGINT时,只需调用server :: shutdown。