网站优化

网站优化

Products

当前位置:首页 > 网站优化 >

QTcpServer的源码中,有哪些可以解构其底层原理与技术细节?

GG网络技术分享 2026-01-24 21:57 3


哎呀妈呀, 今天又要聊聊那个让人头秃的QTcpServer源码了

说实话,每次打开Qt的源码我dou觉得自己像个傻子。真的,那种感觉就像是你在家里找袜子,后来啊翻出了一本外星语的字典。咱们今天就是要硬着头皮去kankan这个QTcpServer到底是个什么鬼东西。你说它是网络编程的核心吧,它确实挺核心的;你说它简单吧,kan那几层封装简直Neng把人绕晕。我就想问问写这些代码的大佬们,你们平时是不是dou不睡觉的?

咱们先不说别的,就说这个底层原理吧。其实我也不是特bie懂,dan是为了凑字数...哦不为了让大家明白,我必须得强撑着讲一讲。QTcpServer这个东西,说白了就是用来监听端口的。端口是什么?端口就是你家的大门编号嘛。有人敲门了你就要去开门。dan是这事儿变得特bie复杂。

从源码角度透视QTcpServer:解构QTcpServer的底层原理与技术细节

那个让人又爱又恨的incomingConnection

不忍卒读。 源码里有个函数叫incomingConnection我kan这个名字kan了大概有一百遍才记住怎么拼。这个函数简直是整个服务器的灵魂啊!当你调用listen之后服务器就开始在那傻等了。等什么呢?等客户端连接啊!一旦有连接过来 Qt的事件循环就会像疯狗一样跳起来ran后调用这个incomingConnection。

我记得有一次调试这个函数,后来啊发现传进去的那个socketDescriptor居然是个负数!当时我就崩溃了负数是个什么鬼?难道是来自异世界的连接吗?后来查了半天资料才发现是自己逻辑写错了尴尬得我想找个地缝钻进去。这个socketDescriptor其实就是操作系统给你的一个句柄, 一个ID,你要拿着这个ID去创建真正的QTcpSocket,最后说一句。。

这里我得插一句题外话,现在的编译器真是太智Neng了也太笨了。智Neng的是它Neng帮你补全hen多代码,笨的是它经常在你不想补全的时候瞎补全。 性价比超高。 昨天我写代码的时候手一抖把整个项目dou给重构了吓得我冷汗dou出来了。

咱们来kankan下面这个表格吧, 虽然我也不知 弯道超车。 道为什么要放这里dan是感觉放这里显得比较专业:

排名 网络库名称 易用性评分 主要用途
1 Qt Network 9.5 跨平台应用开发
2 Boost.Asio 4.0 高性NengC++网络编程
3 libevent 6.5 事件驱动HTTP服务器
4 ACE 2.0 古老的分布式系统
5 ZeroMQ 7.5 消息队列中间件

你kan这表里Boost.Asio那个易用性评分才4.0我是真的给高了。用过的人dou知道那玩意儿模板元编程Neng把你逼疯。 到位。 比一比的话Qt真的是亲妈级别的待遇了。

底层的那些破事:Socket Descriptor到底是个啥玩意儿

接着刚才的话题说。在Linux底下一切皆文件。这 Socket 也是个文件描述符。但在Windows底下呢?它就是个句柄。Qt为了跨平台,把这些乱七八糟的东西dou封装起来了。你在kanQTcpServer源码的时候会发现一堆#ifdef QOSWIN32之类的宏定义。

也是醉了... kan着这些宏定义我就头疼。这就好比你在Zuo饭的时候,菜谱上写着“如guo你用的是煤气灶就炒三分钟,如guo是电磁炉就转五分钟”。烦不烦啊!dan是没办法,这就是跨平台的代价。源码解构的过程中你会发现,QTcpServerPrivate这个类干了hen多脏活累活。

比如说那个listen函数,你以为它是摆设吗?它里面调用了底层的::listen系统调用。如guo失败了怎么办?它会返回错误码。dan是hen多时候错误码特bie模糊,比如“Address already in use”。 反思一下。 哎呀我去,又是被占用!我明明把之前的进程dou杀掉了啊!后来才知道有个TIME_WAIT状态在那里作祟。这种细节如guo你不懂底层原理,真的Neng把键盘敲烂dou不知道问题在哪。

I/O多路复用:听起来hen高大上其实也就那样 说到这里不得不提一下select、poll和epoll这几个老伙计了。Qt在网络这一块用的是什么机制呢?这得kan你用的平台了。技术细节就在这里体现出来了。 在Windows上,Qt通常用的是WSAEventSelecthuo者WaitForMultipleObjects;在Linux上呢老版本可Neng用pollhuo者select新版本肯定是用epoll了Mac那边估计就是kqueue了吧记不太清了反正dou差不多啦!这些机制的目的只有一个别让CPU空转傻等数据过来! 你想啊如guo你的服务器有一万个连接难道你要开一万个线程去轮询吗那还不把内存吃光了suo以必须用I/O多路复用告诉内核“嘿老兄有事儿你就叫我没事儿别烦我”。这就是所谓的。 我又想起来上次去买奶茶的事儿了排队的人真多服务员也是忙得晕头转向这不就是个高并发场景嘛只不过奶茶店用的是先来后服务策略而TCP连接是公平调度罢了扯远了扯远了... 这时候我突然觉得如guo不放个表格好像对不起读者那么再来一个对比表吧这次我们kankan几种I/O模型的区别虽然跟QTcpServer源码没直接关系dan是懂了这个对你理解源码有帮助真的!
I/O模型 并发性Neng 开发难度 适用场景
BIO 极低 简单 学习Demo / 低并发工具
NIO 中等 困难 即时通讯游戏后台等
AIO 地狱级 超大规模服务器集群
多路复用 中等偏难 主流Web服务器 / Qt Network
kan到了吧Qt其实就是帮我们封装好了Zui右边那种模型让你不用直接去跟epoll打交道省去了多少头发啊感谢Qt团队感谢开源社区感谢C++...不对感谢计算机之父图灵先生!

The Event Loop: 无限循环的艺术

我们再回到QTcpServer 本身 当你创建了一个服务器对象并调用了listen之后 它并不会自动跑起来 你需要进入QEventLoop 这个loop就像是一个永动机 只有当程序退出的时候才会停下来 在这个循环里 Qt会不断地检查有没有Socket事件 有没有定时器触发 有没有用户界面geng新请求等等 如guo有一个新的TCP连接到来 底层Socket通知机制就会唤醒EventLoop ran后分发信号 这里有个hen有趣的技术细节 QTcpServer 是tong过QAbstractSocketEngine 来跟底层打交道的 这个Engine类负责读写Socket描述符 你可yi把它想象成一个翻译官 把操作系统的翻译成QtNeng听懂的普通话 dan是我有时候觉得这个翻译官有点笨拙 比如说处理大包分包的时候 如guo你自己写协议解析稍微不注意 就会出现粘包现象 昨天我kan群里还有人问这个问题 我说你去搜搜去吧 这种问题问八百遍了 dou懒得打字解释 说到这里心情有点郁闷 为什么大家dou不爱kan文档呢 文档明明写得那么清楚 虽然是英文的 dan是现在的翻译插件那么多啊 唉 还是贴个表格缓解一下尴尬的情绪吧 这次来个IDE推荐表 毕竟kan源码还得靠好工具:
IDE名称 代码高亮效果 索引速度 是否免费
Visual Studio Code 五彩斑斓的黑 快如闪电
Qt Creator 原生支持Zui好 一般
CLion fei常舒服 JetBrains出品必属精品)
Vim/Neovim 只有黑白全靠脑补颜色) 瞬间完成

线程平安与服务器的并发Neng力瓶颈在哪里?

共勉。 hen多新手拿到QTcpServer 第一反应就是把它移到子线程里去 其实这未必是正确的Zuo法 主要原因是QTcpServer本身的设计并不是线程平安的 它只Neng在创建它的线程也就是主线程里调用listen等方法 dan是incomingConnection可yi在不同线程被触发吗 这就要kan你怎么重写了

如guo你想在子线程处理连接 你通常的Zuo法是在incomingConnection里拿到descriptorran后tong过信号槽发到工作线程去创建socket 这里就涉及到了对象依附性的问题 千万别搞错了 否则程序崩起来连渣dou不剩,说句可能得罪人的话...


提交需求或反馈

Demand feedback