Qt 4.6自带的threaddedfortuneserver是个简单明了的 Qt  C/S网络编程server端程序的例子, 该例子演示了 QTcpServer与QThread配合的方法。 代码不多, 但包含了Qt网络编程的几个关键点。

- FortuneServer类从QTcpServer派生, 调用QTcpServer::listen() 监听端口等待client连接
- FortuneServer重写了虚函数 incomingConnection()去接受client连接,并创建线程处理该连接
- FortuneThread是处理client连接的子线程,  在该线程里向client端写入数据结构非常简单。  笔者本来想照着这个架构写个接收client数据的小server,在写的过程中发现了一个很有意思的问题, 且听我慢慢道来。
     不知道大家有没有发现, 其实FortuneServer这个类看起来是QTcpServer类的简单包装,并没有加入新的东西, 笔者就尝试去掉此子类直接使用QTcpServer。设想的程序架构是这样的:
      - 使用QTcpServer监听端口等待client连接
      - 在收到QTcpServer::newConnection信号时调用nextPendingConnection获得socket 连接, 将socket 连接的fd传送给子线程
       - FortuneThread是处理client连接的子线程,得到连接的fd后创建一个QTcpSocket并用QTcpSocket::setSocketDescriptor,这样就可以用QTcpSocket的方法来监控fd的动向了。这里我们用QTcpSocket::waitForReadyRead等待client端发来的数据为了得到与client的连接的socket fd, 调用了QTcpServer::nextPendingConnection()方法获得一个QTcpSocket指针从该指针得到连接的fd, 再将该fd传送给子线程去处理。 看上去与原来的程序没什么区别, 但运行起来却发生了奇怪的问题,那就是有时server的waitForReadyRead返回true时却读不到数据(bytesAvailable() = 0)似乎client发来的数据丢了一样。 真是让人百思不得其解。

问题出了nextPendingConnection上。仔细回想一下我们的程序的架构,在server进程里调用nextPendingConnection获得一个QTcpSocket的指针,将此指针内的fd信息发送给子进程由子进程负责与client通讯。大家再想想QTcpSocket提供了那么多的API包括signal等, 这意味着什么?肯定Qt在底层对fd进行了监控啊,也就是说在我们的程序里出现了两个QTcpSocket分别在两个线程里对同一个fd进行了监控和操作,所以出现一些奇怪的现象也就不算奇怪了。 如果大家尝试对主线程的QTcpSocket进行处理就会发现,所谓“丢失”的数据都可以在这个socket里得到, 即有一部分socket的数据由于线程切换的关系由主线程的socket截获了。为了解决这个问题当然最好的办法还是沿用例子中的架构, 对QTcpServer进行派生,因为在incomingConnection的参数里可以直接得到fd,此时还没有创建QTcpSocket对此fd做任何操作, 是个干净的状态, 不会有任何冲突;另外还有一个办法是在不改变现有程序架构的情况下把这两个QTcpSocket搬到同一个线程里。这样也不会出现两个线程同时访问一个fd的情况。 具体是使用 QObject::moveToThread方法。  需要注意的是文档中对moveToThread有个说明, 有parent的object是不能被移动到其他线程中的,所以还需要把QTcpSocket给setParent(NULL)一下再moveToThread.
    经过实验, 第二种方法也可以很好的工作。

jerry建议从QTcpServer派生(当然对象可以通过 QObject::moveToThread方法移到其它线程中),不建议第二种方法。

Qt封装QTcpServer参考资料--QT自带QTcpServer架构分析的更多相关文章

  1. Qt编程可不可以结合其他的第三方库和本土API?(有zeroMQ的Qt封装,还可轻易使用Python的库)

    作者:渡世白玉链接:http://www.zhihu.com/question/29030777/answer/59378712来源:知乎著作权归作者所有,转载请联系作者获得授权. 可以,十分可以,你 ...

  2. 官网下载qt-opensource-windows-x86-mingw482_opengl-5.3.1.exe。封装好了Qt libraries、Qt Creator。只需要这一个可执行程序就好了。

    官网下载qt-opensource-windows-x86-mingw482_opengl-5.3.1.exe( http://qt-project.org/downloads).这个可执行程序已经为 ...

  3. Qt+ECharts开发笔记(四):ECharts的饼图介绍、基础使用和Qt封装百分比图Demo

    前言   前一篇介绍了横向柱图图.本篇将介绍基础饼图使用,并将其封装一层Qt.  本篇的demo使用隐藏js代码的方式,实现了一个饼图的基本交互方式,并预留了Qt模块对外的基础接口.   Demo演示 ...

  4. Qt+ECharts开发笔记(五):ECharts的动态排序柱状图介绍、基础使用和Qt封装Demo

    前言   上一篇的demo使用隐藏js代码的方式,实现了一个饼图的基本交互方式,并预留了Qt模块对外的基础接口.  本篇的demo实现了自动排序的柱状图,实现了一个自动排序柱状图的基本交互方式,即Qt ...

  5. Qt4.7文档翻译:Qt样式单参考,Qt Style Sheets Reference(超长,超全)

    内容目录 Qt样式单参考 可进行样式设置的部件列表 属性列表 图标列表 属性类型列表 伪状态列表 子控件列表 Qt样式单参考 Qt样式单支持各种属性.伪状态和子控件,这样使得妳能够自行设计部件的外观. ...

  6. Qt Pro文件与Qt模块启用

    看qt论坛中经常有人忘记 QT+=network 等语句.随便写写吧,或许对他人有帮助. 一.从哪开始呢 不妨先看个例子吧: #include <QtCore/QCoreApplication& ...

  7. Qt Examples - Boxes (在Qt场景视图中结合OpenGL渲染)

    QT自带例程Boxes使用QT Graphics View框架实现了2D图形和3D图形的混合渲染,综合性比较强,整合知识较多,值得学习. 可以使用鼠标通过以下方式控制演示中的元素: 按住鼠标左键的同时 ...

  8. Qt是什么?Qt简介(非常全面)

    http://c.biancheng.net/view/1792.html Qt(官方发音 [kju:t],音同 cute)是一个跨平台的 C++ 开发库,主要用来开发图形用户界面(Graphical ...

  9. PyQt(Python+Qt)学习随笔:Qt Designer中部件的toolTip、toolTipDuration、statusTip、whatsThis属性

    toolTip属性 toolTip属性设置部件的toolTip提示信息,toolTip提示信息在鼠标放到控件上会浮动出一个小框显示提示信息.默认情况下,仅显示活动窗口子部件的toolTip,可以通过在 ...

随机推荐

  1. 【Unity】11.1 角色控制器 (Character Controller)

    分类:Unity.C#.VS2015 创建日期:2016-05-02 一.简介 角色控制器(Character Controller)主要用于对第三人称或第一人称游戏主角的控制.如果要创建类人角色,可 ...

  2. hdu 1879 继续通畅工程(最小生成树)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1879 /************************************************* ...

  3. Oracle根据表生成系统流水号

    1.建表tablewater create table TABLEWATER ( tb_id INTEGER not null, vc_table_name ), num_water_no ) )vc ...

  4. 简单的sqlhelper的学习日志

    一:今天做了一个简单的sqlhelper,还有调用,将今天学的内容总结一下,解决方案如下: 二:对应的sqlhelper的内容: using System; using System.Collecti ...

  5. django rest_framework入门五-认证和权限

    1.django User实体 django自带了用户验证模块,django/contrib/auth/models.py定义了用户实体,代码如下: class AbstractUser(Abstra ...

  6. 20、uwp打包失败(All app package manifests in a bundle must declare the same values under the XPath *[local-name()='Package']/*[local-name()='Dependencies'])

    在给 uwp工程打商店包的时候,遇到了一个异常: Error info: error 80080204: All app package manifests in a bundle must decl ...

  7. Unity编辑器下,界面替换NGUI字体以及字号

    项目中有需要批量替换字体以及字号的需求,一般也就是多语言处理吧. 提供界面如下: 手机拍图,就这样凑合看吧.但是代码不打折. 紧急避让,我只提供修改UILabel以及UIPopupList 下的字体, ...

  8. vue中使用animate.css动画库

    1.安装: npm install animate.css --save 2.引入及使用: //main.js中 import animated from 'animate.css' Vue.use( ...

  9. Python如何下载文件

    转载自:http://www.codecho.com/how-to-download-a-file-in-python/ 利用程序自己编写下载文件挺有意思的.Python中最流行的方法就是通过Http ...

  10. 网络构建入门技术(2)——IP子网划分

    说明(2017-5-10 10:54:31): 1. 为什么要子网划分? 子网划分就是,网络位变长,主机位变短的过程.实际上就是将一个大网络,划分成多个小网络的过程. 目的就是为了解决IP地址不够用的 ...