陈硕 (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 #ifndef MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H
2 #define MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H
3 #include < muduo / net / TcpServer.h >
4 // RFC 862
5 class EchoServer
6 {
7 public :
8 EchoServer(muduo::net::EventLoop * loop,
9 const muduo::net::InetAddress & listenAddr);
10 void start();
11 private :
12 void onConnection( const muduo::net::TcpConnectionPtr & conn);
13 void onMessage( const muduo::net::TcpConnectionPtr & conn,
14 muduo::net::Buffer * buf,
15 muduo::Timestamp time);
16 muduo::net::EventLoop * loop_;
17 muduo::net::TcpServer server_;
18 };
19 #endif // MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H
1 EchoServer::EchoServer(EventLoop * loop,
2 const InetAddress & listenAddr)
3 : loop_(loop),
4 server_(loop, listenAddr, " EchoServer " )
5 {
6 server_.setConnectionCallback(
7 boost::bind( & EchoServer::onConnection, this , _1));
8 server_.setMessageCallback(
9 boost::bind( & EchoServer::onMessage, this , _1, _2, _3));
10 }
11
12 void EchoServer::start()
13 {
14 server_.start();
15 }
1 void EchoServer::onConnection( const TcpConnectionPtr & conn)
2 {
3 LOG_INFO << " EchoServer - " << conn -> peerAddress().toHostPort() << " -> "
4 << conn -> localAddress().toHostPort() << " is "
5 << (conn -> connected() ? " UP " : " DOWN " );
6 }
7
8 void EchoServer::onMessage( const TcpConnectionPtr & conn,
9 Buffer * buf,
10 Timestamp time)
11 {
12 string msg(buf -> retrieveAsString());
13 LOG_INFO << conn -> name() << " echo " << msg.size() << " bytes at " << time.toString();
14 conn -> send(msg);
15 }
1 #include " echo.h "
2 #include < muduo / base / Logging.h >
3 #include < muduo / net / EventLoop.h >
4 using namespace muduo;
5 using namespace muduo::net;
6 int main()
7 {
8 LOG_INFO << " pid = " << getpid();
9 EventLoop loop;
10 InetAddress listenAddr( 2007 );
11 EchoServer server( & loop, listenAddr);
12 server.start();
13 loop.loop();
14 }
完整的代码见 muduo/examples/simple/echo。
这个几十行的小程序实现了一个并发的 echo 服务程序,可以同时处理多个连接。
对这个程序的详细分析见下一篇博客《Muduo 网络编程示例之一:五个简单 TCP 协议》
(待续)