我需要创建一个TCP客户端/服务器应用程序,其中(单个)客户端根据用户命令将请求发送到服务器,同时还要发送定期的“看门狗”消息。看门狗消息需要在不延迟服务器的情况下进行处理。如果服务器在看门狗请求到达时仍在处理仍在处理先前的“繁重”请求,则它必须能够尽快回答新请求(阻止当前处理,回答看门狗请求(只是回声),继续进行处理)。
发生这种行为的最佳方法是什么?
我已经阅读了几个主题,但是我不确定要遵循哪个主题才能获得所需的行为。
到目前为止的故事
我有一个(单个)客户端/服务器Qt应用程序。我正在使用信号/插槽异步管理通讯。客户端发送请求,服务器在接收到数据时向应用发出信号,应用解析请求并执行操作,然后确认/否决该请求。假设客户端正在发送单个请求,在发送新请求之前等待ack/nack。
到目前为止,一切都运转良好。
现在,我必须添加一个“看门狗”命令,该命令将由客户端定期发送(例如,使用QTimer),这打破了“单个消息”的假设。认为由于信号/插槽Qt管理,它可以立即使用;事实并非如此简单...
发生的情况是,当用户发送“繁重的处理请求”(可以用应答确认之前在5秒钟的 sleep 中简化)时,客户端也会发送定期的看门狗消息(例如,每秒),但是在服务器上只有在处理终止时,我才会收到一个新的dataReady()信号。
我读了有关通过moveToThread(无法使用它;仍然从不同线程发出套接字的消息)错误或通过子类化QTread(有效,但仍然阻塞)对套接字进行线程化的信息。
我不会提供代码片段(目前),因为它很长,即使是最小的例子也是如此。首先,我会问你什么是最好的方法。
最佳答案
如果您的服务器是单线程服务器,并且在其插槽中处理大量请求,则readyRead()
信号在接收到时会在消息循环中排队(因为一次只能处理一个插槽),直到当前插槽完成后才进行处理,因此服务器无法同时响应ping。您可以1)在处理大量请求时调用qApp->processEvents();
,或2)将处理移至另一个线程(使用worker)。我将使用第二种选择,因为代码以这种方式更具可读性(我认为)。根据经验:如果您希望某些东西能够响应(GUI,服务器等),请避免笨重的事情。这是第二种方法的粗略实现:https://github.com/mugiseyebrows/concurrent-requests
关于multithreading - 使用QTcpServer/QTcpSocket管理来自单个客户端的并发请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49007611/