QTcpSocket真的是全双工的吗?

Posted

技术标签:

【中文标题】QTcpSocket真的是全双工的吗?【英文标题】:QTcpSocket is really full duplex? 【发布时间】:2015-03-15 06:37:39 【问题描述】:

BSD 流套接字是全双工的,这意味着两个连接方可以同时发送/接收。

一个QTcpSocket(qt socket实现)支持异步,非阻塞模式,但只能属于一个线程,见qt docs。

事件驱动对象只能在单个线程中使用。 具体来说,这适用于定时器机制和网络 模块。

假设我想要一个传输/发送线程和一个单独的接收/接收线程来使用同一个套接字并同时发送/接收数据。

据我了解,这可以通过 qt 信号/插槽“完成”,但套接字线程永远不会真正同时执行 send() 和 receive()。它只是运行事件循环,它将以串行方式执行此操作,并在发送/接收完成时发出信号。

是的,我的 rx 和 tx 线程可以同时工作并通过 qt 插槽处理通知,但套接字本身从未真正用于全双工模式。

这样说是否正确:仅考虑一个端点,在套接字线程中,它的 send() 和 receive() 调用总是串行的,从不同时的? (因为事件循环线程只有一个线程)

【问题讨论】:

“假设我想要一个 tx 线程和一个单独的 rx 线程来使用同一个套接字并同时发送/接收数据。”不,不能这样做。给定套接字上的所有操作必须在同一个线程中执行。如果您尝试您提出的建议,它将使几个 Qt 调试断言失败。此外,要将套接字放在与QTcpServer 不同的线程中,您需要对其进行子类化并做一些小技巧。 在我的示例中有三个线程:socket 线程、rx 线程和 tx 线程。 Socket 线程运行事件循环,并且是唯一执行实际 send()/receive() 的线程。 Rx 和 Tx 线程只是通过信号/插槽或事件来操作套接字。这是 100% 可能的。我的问题是关于套接字线程中真正发生的事情,事件循环实际上是在序列化套接字调用。 【参考方案1】:

据我了解,这可以通过 qt 信号/插槽“完成”,但是 套接字线程永远不会真正执行 send() 和 receive() 同时地。它只是运行事件循环,它将在 串行方式并在发送/接收完成时发出信号。

是的,但请记住,内核缓冲传入和传出数据,并且 QTCPSocket 将套接字设置为非阻塞,因此 send() 和 recv() 调用总是立即返回并且永远不会阻塞事件循环。这意味着发送和接收数据的实际过程将同时发生(在内核内部),即使(或多或少是瞬时的)send() 和 recv() 调用在技术上不会发生。 (*)

是的,我的 rx 和 tx 线程可以同时工作并处理 通过 qt 插槽通知,但套接字本身从未真正使用过 在全双工模式下。这是正确的吗?

这是不正确的——套接字的数据流可以(并且确实)同时通过网络双向流动,因此套接字实际上是全双工的。无论您使用的是单线程还是多线程,全双工功能都存在。

(*) 您可以使用单线程 Qt 程序进行测试,该程序使用 QTCPSocket 发送或接收数据,只需在大数据传输期间断开计算机的以太网电缆即可。如果 QTCPSocket 的 send() 或 recv() 调用在完成之前一直阻塞,这将阻塞 GUI 线程并导致 GUI 变得无响应,直到您重新连接电缆(或直到几分钟后 TCP 连接超时)。

【讨论】:

以上是关于QTcpSocket真的是全双工的吗?的主要内容,如果未能解决你的问题,请参考以下文章

I2C,485,232,spi这四种通信方式有啥区别?啥是双工,啥是半双工,啥是全双工?

TCP是双向的还是全双工的?

全双工

关于网络和带宽(全双工与半双工带宽区别)

Linux 网络编程详解八

stm32---RS485半双工通信