zoukankan      html  css  js  c++  java
  • Muduo 网络编程示例之四:Twisted Finger

    陈硕 (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 <muduo/net/EventLoop.h>
       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 <muduo/net/EventLoop.h>
       2: #include <muduo/net/TcpServer.h>
       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<string, string> 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<string, string> 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.

    冒烟测试过关。

    (待续)

  • 相关阅读:
    抽象类 C#
    多态
    父类与子类的转换as,is
    try catch finally 与continue的使用
    封装、多态、继承
    new关键字 、this关键字、base关键字
    进程的使用
    Spring IOC
    使用annotation配置hibernate(3):一对一关系配置
    使用annotation配置hibernate(3):多对多关系配置
  • 原文地址:https://www.cnblogs.com/Solstice/p/1963197.html
Copyright © 2011-2022 走看看