您的位置:首页 > 理论基础 > 计算机网络

Muduo 网络编程示例之四:Twisted Finger

2011-02-23 21:34 357 查看
陈硕 (giantchen_AT_gmail)

Blog.csdn.net/Solstice

这是《Muduo 网络编程示例》系列的第四篇文章。

Muduo 全系列文章列表: http://blog.csdn.net/Solstice/category/779646.aspx

Python Twisted 是一款非常好的网络库,它也采用 Reactor 作为网络编程的基本模型,所以从使用上与 muduo 颇有相似之处。(当然,muduo 没有 deferreds)Finger 是 twisted 文档的一个经典例子,本文展示如何用 muduo 来实现最简单的 finger 服务端。限于篇幅,只实现 finger01~07。代码位于 examples/twisted/finger

1 拒绝连接

什么都不做,程序空等。finger01.cc

1: #include


2:


3: using namespace muduo;


4: using namespace muduo::net;


5:


6: int main()


7: {


8:   EventLoop loop;


9:   loop.loop();


10: }


2 接受新连接

在 1079 端口侦听新连接,接受连接之后什么都不做,程序空等。muduo 会自动丢弃收到的数据。finger02.cc

1: #include


2: #include


3:


4: using namespace muduo;


5: using namespace muduo::net;


6:


7: int main()


8: {


9:   EventLoop loop;


10:   TcpServer server(&loop, InetAddress(1079), "Finger");


11:   server.start();


12:   loop.loop();


13: }


3 主动断开连接

接受新连接之后主动断开。finger03.cc

以下省略头文件和 namespace。

1: void onConnection(const TcpConnectionPtr& conn)


2: {


3: if (conn->connected())


4:   {


5:   conn->shutdown();


6: }


7: }


8:


9: int main()


10: {


11:   EventLoop loop;


12:   TcpServer server(&loop, InetAddress(1079), "Finger");


13:   server.setConnectionCallback(onConnection);


14:   server.start();


15:   loop.loop();


16: }


4 读取用户名,然后断开连接

如果读到一行以 /r/n 结尾的消息,就断开连接。finger04.cc

注意这段代码有安全问题,如果恶意客户端不断发送数据而不换行,会撑爆服务端的内存。另外,Buffer::findCRLF() 是线性查找,如果客户端每次发一个字节,服务端的时间复杂度为 O(N^2),会消耗 CPU 资源。

1: void onMessage(const TcpConnectionPtr& conn,


2:              Buffer* buf,


3:              Timestamp receiveTime)


4: {


5: if (buf->findCRLF())


6: {


7:     conn->shutdown();


8: }


9: }


10:


11: int main()


12: {


13:   EventLoop loop;


14:   TcpServer server(&loop, InetAddress(1079), "Finger");


15:   server.setMessageCallback(onMessage);


16:   server.start();


17:   loop.loop();


18: }


5. 读取用户名、输出错误信息、然后断开连接

如果读到一行以 /r/n 结尾的消息,就发送一条出错信息,然后断开连接。finger05.cc

安全问题同上。

1: void onMessage(const TcpConnectionPtr& conn,


2:              Buffer* buf,


3:              Timestamp receiveTime)


4: {


5: if (buf->findCRLF())


6: {


7:     conn->send("No such user/r/n");


8:   conn->shutdown();


9:   }


10: }


11:


12: int main()


13: {


14:   EventLoop loop;


15:   TcpServer server(&loop, InetAddress(1079), "Finger");


16:   server.setMessageCallback(onMessage);


17:   server.start();


18:   loop.loop();


19: }


6. 从空的 UserMap 里查找用户

从一行消息中拿到用户名(第 22 行),在 UserMap 里查找,然后返回结果。finger06.cc

安全问题同上。

1: typedef std::map UserMap;


2: UserMap users;


3:


4: string getUser(const string& user)


5: {


6: string result = "No such user";


7:   UserMap::iterator it = users.find(user);


8: if (it != users.end())


9:   {


10:   result = it->second;


11: }


12:   return result;


13: }


14:


15: void onMessage(const TcpConnectionPtr& conn,


16:                Buffer* buf,


17:                Timestamp receiveTime)


18: {


19:   const char* crlf = buf->findCRLF();


20:   if (crlf)


21:   {


22:     string user(buf->peek(), crlf);


23:     conn->send(getUser(user) + "/r/n");


24:     buf->retrieveUntil(crlf + 2);


25:     conn->shutdown();


26:   }


27: }


28:


29: int main()


30: {


31:   EventLoop loop;


32:   TcpServer server(&loop, InetAddress(1079), "Finger");


33:   server.setMessageCallback(onMessage);


34:   server.start();


35:   loop.loop();


36: }


7. 往 UserMap 里添加一个用户

与前面几乎完全一样,只多了第 31 行。finger07.cc

1: typedef std::map UserMap;


2: UserMap users;


3:


4: string getUser(const string& user)


5: {


6: string result = "No such user";


7:   UserMap::iterator it = users.find(user);


8: if (it != users.end())


9:   {


10:   result = it->second;


11: }


12:   return result;


13: }


14:


15: void onMessage(const TcpConnectionPtr& conn,


16:                Buffer* buf,


17:                Timestamp receiveTime)


18: {


19:   const char* crlf = buf->findCRLF();


20:   if (crlf)


21:   {


22:     string user(buf->peek(), crlf);


23:     conn->send(getUser(user) + "/r/n");


24:     buf->retrieveUntil(crlf + 2);


25:     conn->shutdown();


26:   }


27: }


28:


29: int main()


30: {


31:   users["schen"] = "Happy and well";


32:   EventLoop loop;


33:   TcpServer server(&loop, InetAddress(1079), "Finger");


34:   server.setMessageCallback(onMessage);


35:   server.start();


36:   loop.loop();


37: }


以上就是全部内容,可以用 telnet 扮演客户端来测试我们的简单 finger 服务端。

Telnet 测试

在一个命令行窗口运行

$ ./bin/twisted_finger07

另一个命令行运行

$ telnet localhost 1079

Trying ::1...

Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

muduo

No such user

Connection closed by foreign host.

再试一次

$ telnet localhost 1079

Trying ::1...

Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

schen

Happy and well

Connection closed by foreign host.


冒烟测试过关。

(待续)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: