启动连接后将 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 移动到新线程的主要内容,如果未能解决你的问题,请参考以下文章