一、问题描述:

你之所以会来看我这篇文章,大概是遇到了一下几个问题:

1、使用QTcpSocket时,readyread函数没有触发,或者触发了,但是触发次数不是自己想象的那样。

2、readyread槽函数中,接收到的数据不对。

我们先看一下Qt官方文档的说法:

官方文档中对readyread函数解释很简短:

This signal is emitted once every time new data is available for reading from the device's current read channel. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.

//让我来解释给你这句话的意思,解释完你就会有新的认识。//

每一次,在当前用来存放读数据的位置中(也就是可读缓冲区),有可读数据可用,都会发送这个信号。当新的数据到来的时候,这个信号还会再发送且仅发送一次。比如:新的网络数据到达你的网络socket,或者新的数据块添加到你的设备。

我们一句一句话来理解,首先是:“每一次,在当前用来存放读数据的位置中(也就是可读缓冲区),有可读数据可用,都会发送这个信号”。这句话的意思是,当你的QTcpSokcet第一次接收到数据,也就是socket的缓冲区从没有数据变为有数据时,触发一次。

接下来非常关键的一句话是:“当新的数据到来的时候,这个信号还会再发送且仅发送一次。”很多朋友对新的数据到来的错误理解是,发送端对应的QTcpSokcet写一次,也就是write函数调用一次,那么接收方就会有新的数据到达,于是readyread信号被触发一次。这个理解是错误的。经过测试,我们发现事实是这样的:发送和接收的次数是没有一一对应关系的。发送端write函数调用一次,假如这一次write了2M的数据,那么接收方的readyread信号就往往会触发两次以上。反过来,如过发送端write函数被调用两次或两次以上,每次发送的数据量很小,比如两三个字节,那么接收方的readyread信号也有可能只触发一次。

这是什么回事呢?文档明明说有新的数据来,就会帮我触发一次。其实啊,这里说新的数据来,不是说从发送端有新的数据来到你的主机,而是数据从Tcp/ip协议栈到达接收端的Qt应用程序,也就是系统io缓冲区到达Qt应用程序,数据从系统到达Qt应用程序一次,readyread信号就会触发一次。

还有一个非常要注意的词就是“only once”,仅仅一次。什么意思呢?其实是这样的,第一次数据来的时候,触发一次readyread信号,但如果此时你的readyread槽函数还没有及时执行,或者从根本上说QTcpsocket对象的byteAvailable函数返回值还不为0,而新的数据又来了而且来了很多次,那么,这些所有的都将会只再触发一次readyread信号。如果此时你的readyread槽函数执行了,那么这时候来的新的数据就会触发第三个readyread信号。也就是说,还没有响应的readyread信号最多只有两个。想想也是啊,如果我发送端一直发送数据,你的系统就一直接收并将数据发送给你的应用,然后每得到一个字节都触发一次readyRead信号,触发到成千上万个,那击崩一个服务器不就很简单了?

最后一个关键词,那就是“数据”。通过上面的介绍,你可能也意识到了,既然发送和接收没有一一对应关系,那么我接收到的东西到底是什么样子的?这时候你就需要对数据流有一定的认识。数据从另一端以流的方式流进了你的机子。数据到了的时候,系统就会通过数据报的端口来识别这个数据是要发送给这台机子的哪个应用程序。注意TCP和udp的数据是有区别的,tcp数据包没有边界,udp有。也就是说对于tcp,数据是连在一起的分不开的,最小粒度是1字节。发送端的应用程序write函数一次写了多少数据,接收方的系统是不知道的。那么接收方系统到底接收到多少数据才发送给qt应用程序呢?这个算法是这样的:超时和超过缓冲。超时:无论来了多少数据,超过这个时间,系统就会发送当前接收到的数据给qt应用程序。超过缓冲,在未超时的情况下,系统缓冲区满了,系统就会将数据发送给qt应用程序。系统TCP/IP缓冲最大是65536个字节。

根据以上机制,在readyread槽函数中,调用QTcpSocket的byteAvailable函数返回的值,是不可预知的,取决于系统发给应用时,发送的数量,这个数量的最大值就是65536字节。这个byteAvailable函数返回的值,就是本次readyread槽函数中所能读到的网络数据量。如果在你正在读取数据时,又有新的数据到来,byteAvailable返回的值是不会被影响的。你读了多少数据,byteAvailable就会减去多少数据。如果用的是readAll函数就是读完,byteAvailable就会返回0。注意:网上流传这很多用流的方式接收数据,在readyread槽函数还没有结束之前,QTcpSocket缓存数据是不会清除掉的,所以byteAvailable返回值从槽函数开始到结束都不会变。(流其实就是序列化,流进和流出数据类型要保持一致,谨慎使用。)readyRead信号这样的触发机制,就可能会存在黏包问题,关于黏包问题的解释和解决方案网上已经有很多很优秀的文章了,我就不赘述了。

最后,要是还没有解决你的readyread函数还是没有触发,看看是不是防火墙有没有禁掉你的qt应用,有没有关掉VPN。

如何正确使用QTcpSocket的readyRead信号?相关推荐

  1. qt网络编程及readyread信号

    最近搞了个需求涉及进程ipc,使用的是qt中qlocalserver和qlocalsocket.看了文档,这个qlocalsocket在win平台上其实就是用的命名管道.编程方式类似socket编程, ...

  2. STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号

    STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号 一. 问题描述 二. 方法一--使用HAL_UART_Receive_DMA 三. 方法二--使用HAL_UARTEx_Rece ...

  3. readyread信号不触发_触发器型PFD与传统型PFD性能仿真对比

    @TOC 鉴频鉴相器中为了保证鉴相范围,主要有两种PFD可以在理想情况下实现 到 的鉴相范围. 传统的PFD和边沿触发型的PFD 1.电路结构 1.1传统型电路结构 参考文献:宽带CMOS分数频率合 ...

  4. wi-fi测试软件正确吗,几款Wi-Fi信号测试小工具

    原标题:几款Wi-Fi信号测试小工具 今天就为大家介绍几种测试WiFi信号强度方法,有了它们的帮助,还愁没有好WiFi吗? 方法一:小白都会用的Wi-Fi信号强度测量法 无论是智能手机,还是PAD,抑 ...

  5. 专业音频如何把电平转换成dbu_正确理解音频设备的电平信号

    观察设备之间通过的电平信号表,并对观察到的结果检查与调整,对于行业新人来说是比较困难的.但是一旦你掌握了几点基本的技巧,那么它对你来说会是一个很有用的工具. 一般来说音频工作者会遇到三种常见的电平表达 ...

  6. qtcpsocket断开_2020-05-06 QT子线程使用QTcpSocket连接服务器

    为什么要是用多线程? 多线程的使用主要是为了处理比较耗时的过程.多线程的实现可以通过两种方式实现 分别是:1.继承QThread实现多线程2.继承QObject实现多线程(由于继承QObject的多线 ...

  7. Qt4_写TCP客户/服务器应用程序

    写TCP客户/服务器应用程序 QTcpSocket和QTcpServer类可以用来实现TCP客户端和服务器.TCP是一个传输协议,它构成了包括FTP和HTTP等很多应用程序层的因特网协议基础,它也可以 ...

  8. 具有路线规划功能的外卖平台(Qt,C++,C/S架构,MySql)

    你好,这篇文章记录了我的一次课程设计的全过程,如果能够帮助到你,我将十分荣幸. 如果你有不同的见解,欢迎在讨论区与我交流. 先展示部分系统界面.设计流程及业务测试详情见后文 文章目录 0. 系统界面截 ...

  9. vs2008编译QT开源项目--太阳神三国杀源码分析(四) 动画

    太阳神三国杀中,每当玩家出杀或吃桃子时,就会有一个动画效果,使界面非常生动绚丽.现在我们就分析一下QT中动画的原理,及实现方式,这里我们只分析吃桃子时的动画效果实现.由于三国杀有多个在线玩家同时游戏, ...

  10. vs2008编译QT开源项目--太阳神三国杀源码分析(二) 客户端添加武将

    接着上篇文章继续分析,我们来看看进入到roomScene(房间场景)后,点击add a robot按钮,是如何创建武将的.首先找到add to robot按钮的创建代码: add_robot = ne ...

最新文章

  1. Spring Cloud(六)服务网关 zuul 快速入门
  2. pytorch 模型可视化_高效使用Pytorch的6个技巧:为你的训练Pipeline提供强大动力
  3. python爬取页面链接
  4. 央视曝光:刷单实为非法商业模式 步步设置全是套路
  5. php将文件夹打包zip文件,php将文件夹打包成zip文件
  6. #1049 : 后序遍历(二叉树,DFS)
  7. Awesome Tools Site
  8. 2017电大c语言考试时间,2017年电大 《c语言程序设计》a课程考核说明.doc
  9. 博客园博客开通了,庆贺一下
  10. 所有的 iPhone 和高端 Android 设备都被破解了!
  11. 如何编写兼容各主流邮箱的HTML邮件
  12. 面试题(4)--基础篇
  13. RHCE 第三讲 文件系统
  14. ubuntu wine protel 99se安装
  15. Android之输入银行卡号判断属于哪个银行
  16. 现代操作系统 第三章 内存管理 习题
  17. 电子技术部下半学期第一次培训
  18. 开篇记(好记性不如烂笔头)
  19. node内存溢出:JavaScript heap out of memory
  20. QQ远程提示系统权限原因暂时无法操作怎么办

热门文章

  1. oracle12162错误,ORA-12162: TNS:net service name is incorrectly specified报错问题如何解决?...
  2. 字体图标的设置(阿里巴巴矢量图库的使用)
  3. Kali 安装 xmapp、DVWA
  4. LabVIEW开放神经网络交互工具包【ONNX】,大幅降低人工智能开发门槛,实现飞速推理
  5. 【参考文献格式】 GB/T 7714, MLA ,APA
  6. eplan 电箱布局_Eplan 的从头到尾完成3D布局步骤说明
  7. cobar mysql 性能_Cobar
  8. d3中元素拖拽drag实例
  9. java pdf 水印 加密_Java生成PDF 加密 水印
  10. SqlServer数据库 设置查询结果字体