陈硕 (giantchen_AT_gmail)
Blog.csdn.net/Solstice
Muduo 全系列文章列表: http://blog.csdn.net/Solstice/category/779646.aspx
我将会写一系列文章,介绍用 muduo 网络库完成常见的 TCP 网络编程任务。目前计划如下:
-
UNP 中的简单协议,包括 echo、daytime、time、discard 等。
-
Boost.Asio 中的示例,包括 timer2~6、chat 等。
-
Java Netty 中的示例,包括 discard、echo、uptime 等,其中的 discard 和 echo 带流量统计功能。
-
Python twisted 中的示例,包括 finger01~07
- 用于测试两台机器的往返延迟的 roundtrip
- 用于测试两台机器的带宽的 pingpong
-
云风的串并转换连接服务器multiplexer,包括单线程和多线程两个版本。
- 文件传输
- 一个基于 TCP 的应用层广播 hub
- socks4a 代理服务器,包括简单的 TCP 中继(relay)。
- 一个 Sudoku 服务器的演变,从单线程到多线程,从阻塞到 event-based。
- 一个提供短址服务的 httpd 服务器
其中前面 7 个已经放到了 muduo 代码的 examples 目录中,下载地址是: http://muduo.googlecode.com/files/muduo-0.1.5-alpha.tar.gz
这些例子都比较简单,逻辑不复杂,代码也很短,适合摘取关键部分放到博客上。其中一些有一定的代表性与针对性,比如“如何传输完整的文件”估计是网络编程的初学者经常遇到的问题。请注意,muduo 是设计来开发内网的网络程序,它没有做任何安全方面的加强措施,如果用在公网上可能会受到攻击,在后面的例子中我会谈到这一点。
本系列文章适用于 Linux 2.6.x (x > 28),主要测试发行版为 Ubuntu 10.04 LTS 和 Debian 6.0 Squeeze,64-bit x86 硬件。
TCP 网络编程本质论
我认为,TCP 网络编程最本质的是处理三个半事件:
- 连接的建立,包括服务端接受 (accept) 新连接和客户端成功发起 (connect) 连接。
- 连接的断开,包括主动断开 (close 或 shutdown) 和被动断开 (read 返回 0)。
- 消息到达,文件描述符可读。这是最为重要的一个事件,对它的处理方式决定了网络编程的风格(阻塞还是非阻塞,如何处理分包,应用层的缓冲如何设计等等)。
- 消息发送完毕,这算半个。对于低流量的服务,可以不必关心这个事件;另外,这里“发送完毕”是指将数据写入操作系统的缓冲区,将由 TCP 协议栈负责数据的发送与重传,不代表对方已经收到数据。
这其中有很多难点,也有很多细节需要注意,比方说:
- 如果要主动关闭连接,如何保证对方已经收到全部数据?如果应用层有缓冲(这在非阻塞网络编程中是必须的,见下文),那么如何保证先发送完缓冲区中的数据,然后再断开连接。直接调用 close(2) 恐怕是不行的。
- 如果主动发起连接,但是对方主动拒绝,如何定期 (带 back-off) 重试?
- 非阻塞网络编程该用边沿触发(edge trigger)还是电平触发(level trigger)?(这两个中文术语有其他译法,我选择了一个电子工程师熟悉的说法。)如果是电平触发,那么什么时候关注 EPOLLOUT 事件?会不会造成 busy-loop?如果是边沿触发,如何防止漏读造成的饥饿?epoll 一定比 poll 快吗?
- 在非阻塞网络编程中,为什么要使用应用层缓冲区?假如一次读到的数据不够一个完整的数据包,那么这些已经读到的数据是不是应该先暂存在某个地方,等剩余的数据收到之后再一并处理?见 lighttpd 关于 \r\n\r\n 分包的 bug。假如数据是一个字节一个字节地到达,间隔 10ms,每个字节触发一次文件描述符可读 (readable) 事件,程序是否还能正常工作?lighttpd 在这个问题上出过安全漏洞。
- 在非阻塞网络编程中,如何设计并使用缓冲区?一方面我们希望减少系统调用,一次读的数据越多越划算,那么似乎应该准备一个大的缓冲区。另一方面,我们系统减少内存占用。如果有 10k 个连接,每个连接一建立就分配 64k 的读缓冲的话,将占用 640M 内存,而大多数时候这些缓冲区的使用率很低。muduo 用 readv 结合栈上空间巧妙地解决了这个问题。
- 如果使用发送缓冲区,万一接收方处理缓慢,数据会不会一直堆积在发送方,造成内存暴涨?如何做应用层的流量控制?
- 如何设计并实现定时器?并使之与网络 IO 共用一个线程,以避免锁。
这些问题在 muduo 的代码中可以找到答案。
Muduo 简介
我编写 Muduo 网络库的目的之一就是简化日常的 TCP 网络编程,让程序员能把精力集中在业务逻辑的实现上,而不要天天和 Sockets API 较劲。借用 Brooks 的话说,我希望 Muduo 能减少网络编程中的偶发复杂性 (accidental complexity)。
Muduo 只支持 Linux 2.6.x 下的并发非阻塞 TCP 网络编程,它的安装方法见陈硕的 blog 文章。
Muduo 的使用非常简单,不需要从指定的类派生,也不用覆写虚函数,只需要注册几个回调函数去处理前面提到的三个半事件就行了。
以经典的 echo 回显服务为例:
1. 定义 EchoServer class,不需要派生自任何基类:
在构造函数里注册回调函数:
2. 实现 EchoServer::onConnection() 和 EchoServer::onMessage():
3. 在 main() 里用 EventLoop 让整个程序跑起来:
完整的代码见 muduo/examples/simple/echo。
这个几十行的小程序实现了一个并发的 echo 服务程序,可以同时处理多个连接。
对这个程序的详细分析见下一篇博客《Muduo 网络编程示例之一:五个简单 TCP 协议》
(待续)
分享到:
相关推荐
《muduo 木铎:探索中国开源的多线程编程库》 “muduo”是一个由中国开发者编写的开源库,专为多线程编程设计。它以其高效、稳定和易于使用的特性,在国内的软件开发领域中逐渐受到广泛关注。在深入理解muduo之前,...
中国光大银行信用卡网上商城系统设计与实现_杨木铎
颜渊对孔子的赞美体现了儒家重视个人修养,追求"仰之弥高,钻之弥坚"的精神境界。同时,孔子强调"诲人不倦",体现其对教育的重视。 6. 孔子的教育理念: 孔子的教学方法注重引导,"循循然善诱人",通过丰富的知识...
"木铎(yí)",古代宣布政教法令时,摇动木舌铜铃,此处可能是误读;"不得与(yù)于斯文",意为不能参与这种文化活动;"怃然(wǔ)",形容怅然失意的样子;"食黍(shǔ)",吃黄米;"击磬(qìng)",敲击乐器;"敝(bì)之...
- 选取仪封人的故事,通过他的赞誉,凸显孔子作为“木铎”的角色,即传播道德和教化的使者,展示孔子在当时社会中的崇高地位和影响。 通过这个教案,学生不仅可以学习到古代汉语,还能深入了解孔子和他的儒家思想...
《论语》是中国古代儒家经典之一,记录了孔子及其弟子的言行,是研究孔子思想的重要文献。宋代朱熹将其与其他三部经典——《大学》、《中庸》、《孟子》并称为“四书”。《论语》分为20篇,每篇由若干章节组成,章节...
据《周礼》记载,当时就已经有了防火措施:“春秋,以木铎修火禁”,意即在春秋两季,用木铎来提醒百姓注意防火。到了北宋时期,社会经济和城市规模的发展促使消防工作的形态进一步变化。汴京(即今天的开封)设立了...
这四个结构成分——木铎、禁火、冷食、再取天火,在不同文化中以不同的形式出现,但都反映了人类共同的思维模式和对自然界变化的响应。木铎和木鼓等音响工具作为仪式的一部分,传达了黑暗与光明的对立,以及自然与...
8. 掌握多义词的不同含义,比如“沉疴”既有拖延长久的重病之意,也可以指难以治愈的顽固病症。 9. 学习描述人物或事物状态的词语,例如“岑寂”形容环境高而静,清冷,“轻佻”则形容举止不稳重。 10. 认识一些常...
《论语》是儒家经典之一,记录了孔子及其弟子的言行,主要反映了儒家的哲学思想、道德观念和社会伦理。在高中语文《先秦诸子选读》第一单元中,我们选取了《论语》的部分章节进行研读,这些篇章展示了孔子和他的弟子...
汉代乐府的采集方法,受到了《尚书》中夏代“遒人”收集民间歌谣方式的启发,即通过振木铎收集民谣,使之成为礼乐制度的一个组成部分。汉代乐府民歌,尤其是非核心的乐府歌曲部分,如“鼓吹曲辞”、“横吹曲辞”等,...
1. 新闻传播的起源与发展:中国古代的新闻传播可以追溯到夏、商、周时期的“遒人”,他们摇动木铎在各地巡行,宣达政令,这是我国新闻事业的最早形态。新闻传播在唐朝之前主要通过非文字载体进行,如拟态、手势、...
他的“木铎”形象,象征着他在传播知识和道德上的使命,但这并不意味着他应该被严格定义为史家。 综上所述,文章探讨了孔子与《春秋》之间的关系,以及孔子是否可以被归类为史家的问题。孔子的历史素养和他对历史的...
孔子被誉为“木铎”,意即传递天道、道德和智慧的使者。这一称谓突显了孔子在道德教化方面的重要作用和不可替代的地位。在当时,人们视孔子为一种超凡脱俗的存在,他是智慧与道德的化身,是理想人格的典范。 针对...
在这一时期,木铎作为一种传播媒介,通过声音传播信息。 在中国新闻史上,唐朝被视为报纸的起源,当时的政府官报(如“敦煌进奏院状”)是封建政府机构内部发行的,具有原始报纸的性质。宋代则出现了在政府中枢部门...
从最早的遒人摇动木铎的原始形态,到清代成熟发达的官报体系,新闻传播的形式和内容在不断地丰富和发展。 夏、商、周时期的遒人是最早的信息传播者,他们通过巡行各地的方式,不仅传达政令,还进行采风,将地方的...
`tf()`函数用于直接建立传递函数,而`zpk()`则用于构建零极点增益模型。这两个函数可以互相转换,以适应不同的分析需求。 实验内容还涉及了系统的组合,如串联、并联和反馈连接。例如,两个子系统的传递函数可以...
数字信号处理是研究用数字方法对信号进行分析、变换、滤波、检测、调制、解调以及快速算法的一门技术学科。但很多人认为:数字信号处理主要是研究有关数字滤波技术、离散变换快速算法和谱分析方法。...
《现代铁路远程控制系统》主要内容有远程控制系统的基本概念、技术基础、调度集中(CTC)系统及应用、铁路列车调度指挥系统(TDCS)、铁路信号微机监测及其实用系统(MMS)、铁路智能交通系统(ITS.R)等。...