启动连接后将 QTcpSocket 移动到新线程

Posted

技术标签:

【中文标题】启动连接后将 QTcpSocket 移动到新线程【英文标题】:Move QTcpSocket to a new Thread after the connection is initiated 【发布时间】:2016-11-08 03:13:41 【问题描述】:

我有一个线程服务器。

QTcpSocket 需要在需要运行的线程上创建,FI: Qt - Handle QTcpSocket in a new thread 通过传递套接字描述符。

我的问题是,我需要有一个线程池,并在客户端发送了一个特定的令牌之后移动特定线程上的套接字,该令牌定义了套接字需要在哪个线程上。

换句话说,我需要先读取套接字以知道将其放置在哪个线程上。

有些想法是首先绑定到 QTcpSocket,读取,然后将描述符发送到线程并创建另一个 QTcpSocket,但文档说:

注意:不能用 相同的本机套接字描述符。

另一种解决方案是在单独的线程中创建套接字,然后将两个线程连接在一起,尽管我不知道这是否可能。

或者也许能够在调用子线程上的 setSocketDescriptor 之前读取主线程上的套接字描述符,如果这可能的话?

【问题讨论】:

出于好奇,您为什么要让客户端告诉您必须在哪个线程上运行QTcpSocket 定义套接字需要在哪个线程上的特定标记 - 我想知道如何指定套接字需要在哪个线程上。 AFAIK 创建线程时不能指定线程 ID。如果你想指定线程名称,你可以调用 thread-->setObjectName("Name") ,这与套接字无关。 为什么不干脆做socket->moveToThread(otherthread)? 码头说不允许 您可以将其视为用户集群的服务器。用户可以创建集群或加入现有集群。每个集群都有自己的线程来提高性能并使用多核。 【参考方案1】:

您完全可以轻松地跨 QThreads 移动套接字,只需注意四件事:

1) 在移动之前确保您的 QTcpSocket 没有父级

2) 在移动之前断开所有与套接字对象的连接

3) 将您需要的任何东西连接回在目标线程中运行的函数中(您可以在线程中使用某种类型的池,在线程拾取它们之前存储那些“移动”的对象

4) 在 init 之后调用 readAll() 可能会错过一些 readyRead() 信号

如果符合设计,没有理由不这样做,至少我多次将它用于多线程服务以跨内核拆分套接字处理程序。

【讨论】:

在写入数据期间您会收到来自QIODevice 的警告。因为不是QTcpSocket的所有字段都可以在线程间移动。 我会尝试找到更多,因为我无法访问代码库。但是有下一个警告:“QSocketNotifier:socket notifiers cannot be enabled from another thread” 没有必要进行任何断开连接——这很愚蠢。其他点是有效的。 QTcpSocket 绝对可以在线程之间移动,至少在 OS X 和 Windows 上,我一直都这样做,而且它确实有效。套接字可能有一个父级,然后您必须在切换线程之前取消它的父级(例如,通过将其作为一个瞬态对象的父级)。 重要的是您从其thread() 访问套接字。理想情况下,操作套接字的控制器对象将成为套接字的父对象,并且您将控制器移动到另一个线程,并且随之而来的是套接字,并且由于连接是直接的,所以一切都很好,但将被调用来自正确线程的事件循环。当你做得对时,它真的一点也不难:) 其实没关系,Fortune Server的例子首先很老很老,在Qt里用了这么多年,通过QTcpSocket绝对没问题

以上是关于启动连接后将 QTcpSocket 移动到新线程的主要内容,如果未能解决你的问题,请参考以下文章

QThread 和 QTcpSocket [关闭]

QTcpSocket真的是全双工的吗?

Qt笔记-QTcpSocket跨线程调用(官方推荐方法,非百度烂大街方法)

QTcpSocket 客户端自动重连

QTcpSocket 及 TCP粘包分析

当主线程无限循环运行时,服务器没有收到用 QTcpSocket::write 写入的字节?