陈硕 (giantchen_AT_gmail)
Blog.csdn.net/Solstice
Muduo 全系列文章列表: http://blog.csdn.net/Solstice/category/779646.aspx
我将会写一系列文章,介绍用 muduo 网络库完成常见的 TCP 网络编程任务。目前计划如下:
其中前面 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 网络编程最本质的是处理三个半事件:
这其中有很多难点,也有很多细节需要注意,比方说:
这些问题在 muduo 的代码中可以找到答案。
我编写 Muduo 网络库的目的之一就是简化日常的 TCP 网络编程,让程序员能把精力集中在业务逻辑的实现上,而不要天天和 Sockets API 较劲。借用 Brooks 的话说,我希望 Muduo 能减少网络编程中的偶发复杂性 (accidental complexity)。
Muduo 只支持 Linux 2.6.x 下的并发非阻塞 TCP 网络编程,它的安装方法见陈硕的 blog 文章。
Muduo 的使用非常简单,不需要从指定的类派生,也不用覆写虚函数,只需要注册几个回调函数去处理前面提到的三个半事件就行了。
以经典的 echo 回显服务为例:
1. 定义 EchoServer class,不需要派生自任何基类:
#ifndef MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H #define MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H #include // RFC 862 class EchoServer { public: EchoServer(muduo::net::EventLoop* loop, const muduo::net::InetAddress& listenAddr); void start(); private: void onConnection(const muduo::net::TcpConnectionPtr& conn); void onMessage(const muduo::net::TcpConnectionPtr& conn, muduo::net::Buffer* buf, muduo::Timestamp time); muduo::net::EventLoop* loop_; muduo::net::TcpServer server_; }; #endif // MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H
在构造函数里注册回调函数:
EchoServer::EchoServer(EventLoop* loop, const InetAddress& listenAddr) : loop_(loop), server_(loop, listenAddr, "EchoServer") { server_.setConnectionCallback( boost::bind(&EchoServer::onConnection, this, _1)); server_.setMessageCallback( boost::bind(&EchoServer::onMessage, this, _1, _2, _3)); } void EchoServer::start() { server_.start(); }
2. 实现 EchoServer::onConnection() 和 EchoServer::onMessage():
void EchoServer::onConnection(const TcpConnectionPtr& conn) { LOG_INFO << "EchoServer - " << conn->peerAddress().toHostPort() << " -> " << conn->localAddress().toHostPort() << " is " << (conn->connected() ? "UP" : "DOWN"); } void EchoServer::onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time) { string msg(buf->retrieveAsString()); LOG_INFO << conn->name() << " echo " << msg.size() << " bytes at " << time.toString(); conn->send(msg); }
3. 在 main() 里用 EventLoop 让整个程序跑起来:
#include "echo.h" using namespace muduo; using namespace muduo::net; int main() { LOG_INFO << "pid = " << getpid(); EventLoop loop; InetAddress listenAddr(2007); EchoServer server(&loop, listenAddr); server.start(); loop.loop(); }
完整的代码见 muduo/examples/simple/echo。
这个几十行的小程序实现了一个并发的 echo 服务程序,可以同时处理多个连接。
对这个程序的详细分析见下一篇博客《Muduo 网络编程示例之一:五个简单 TCP 协议》
(待续)