在C ++中实现应用服务器及其客户端库时,我无法找到一种干净可靠的方法来停止Windows上服务器关闭时的客户端进程。
假设服务器及其客户端在同一用户下运行,则要求为:
在此编辑中,以下大部分答案都提倡在服务器与其客户端之间使用共享内存(或其他IPC机制)来传达关闭命令和客户端状态。这些解决方案可行,但要求客户端成功初始化库。
我没有说的是,服务器也用于启动客户端,在某些情况下,其他程序/脚本根本不使用客户端库。一个不依赖于服务器和客户端之间优雅通信的解决方案会更好(如果可能的话)。
前一段时间,我偶然发现了一个C片段(在我认为的MSDN中)执行了以下操作:
不幸的是,现在我正在寻找它,我无法找到它,搜索结果似乎暗示这个技巧在Vista上不再起作用了。有专家的意见吗?
答案 0 :(得分:2)
如果您使用线程,一个简单的解决方案是使用命名系统事件,线程在等待它发出信号的事件上休眠,控制应用程序可以在它希望客户端应用程序退出时发出信号。
对于UI应用程序,它(线程)可以将消息发布到主窗口,WM_ CLOSE或QUIT我忘记了,在控制台应用程序中它可以发出CTRL-C或者如果主控制台代码循环它可以检查线程设置的一些退出条件。
无论是哪种方式而不是找到告诉他们退出的客户端应用程序,使用操作系统来表示他们应该退出。如果使用WaitForSingleObject来休眠,则休眠线程几乎不会占用CPU占用空间。
答案 1 :(得分:1)
您希望在客户端和服务器之间使用某种IPC。如果所有客户都是孩子,我认为管道最简单;因为它们不是,我想服务器操作的共享内存段可用于注册客户端,发出shutdown命令,并收集客户端成功关闭后发布的返回代码。
在此共享内存区域中,客户端放置其进程ID,以便服务器可以使用TerminateProcess()强制终止任何无响应的客户端(模数据服务器权限)。
答案 2 :(得分:1)
如果您愿意使用IPC路由,请在客户端和服务器之间进行双向正常通信,让服务器请求客户端关闭。或者,如果没有,请让客户进行投票。或者作为最后的手段,应该指示客户端在向服务器发出请求时退出。您可以让库用户注册退出回调,但我知道的最好的方法是在客户端被告知关闭时在客户端库中调用“exit”。如果客户端陷入关闭代码,服务器需要能够通过忽略客户端的数据结构和连接来解决它。
答案 3 :(得分:1)
使用PostMessage或命名事件。
Re:PostMessage - GUI以外的应用程序以及GUI线程以外的线程都可以有消息循环,对于这样的东西非常有用。 (实际上COM在引擎盖下使用了消息循环。)我之前用ATL做过但是有点生疏了。
如果您希望对来自“错误”进程的恶意攻击保持健壮,请将客户端/服务器共享的私钥作为消息中的参数之一。
命名事件方法可能更简单;使用名称是客户端/服务器共享的秘密的CreateEvent,并让相应的应用程序在其主循环中检查事件的状态(例如,WaitForSingleObject的超时为0)以确定是否关闭。
答案 4 :(得分:0)
这是一个非常普遍的问题,并且存在一些不一致之处。
虽然它不是100%规则,但大多数控制台应用程序都会运行完成,而GUI应用程序会一直运行直到用户终止它们(并且服务一直运行直到通过SCM停止)。因此,请求GUI关闭更容易。你发送它们相当于Alt-F4。但是对于控制台程序,你必须发送它们相当于Ctrl-C并希望它们处理它。在这两种情况下,你只需等待。如果这个过程四处乱窜,你可以将它击落(TerminateProcess)并祈祷损坏是有限的。但是你的硬盘可以填满临时文件。
GUI应用程序一般没有退出代码 - 它们会去哪里?并且按定义强制终止的控制台进程不会退出,因此它没有退出代码。因此,在服务器关闭方案中,不要指望退出代码。
如果您连接了调试器,通常无法从其他应用程序关闭该进程。这将使调试器无法调试退出代码!