陈硕 (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.

冒烟测试过关。

(待续)

转载于:https://www.cnblogs.com/Solstice/archive/2011/02/23/1963197.html

Muduo 网络编程示例之四:Twisted Finger相关推荐

  1. Muduo 网络编程示例之零:前言

    陈硕 (giantchen_AT_gmail) Blog.csdn.net/Solstice Muduo 全系列文章列表: http://blog.csdn.net/Solstice/category ...

  2. Muduo 网络编程示例之五: 测量两台机器的网络延迟

    Muduo 网络编程示例之五: 测量两台机器的网络延迟 陈硕 (giantchen_AT_gmail) Blog.csdn.net/Solstice  t.sina.com.cn/giantchen ...

  3. Muduo 网络编程示例之三:定时器

    陈硕 (giantchen_AT_gmail) Blog.csdn.net/Solstice 这是<Muduo 网络编程示例>系列的第三篇文章. Muduo 全系列文章列表: http:/ ...

  4. Muduo 网络编程示例之十:socks4a 代理服务器

    Muduo 网络编程示例之十:socks4a 代理服务器 陈硕 (giantchen_AT_gmail) Blog.csdn.net/Solstice  t.sina.com.cn/giantchen ...

  5. JavaEE 网络编程示例1 UDP套接字数据报编程 == 一发一收

    鲁吼呀,胶己人! 文章目录 JavaEE & 网络编程示例1 & UDP套接字数据报编程 ==> 一发一收 1. 协议分层(回顾) 2. 套接字 Socket 2.1 UDP与T ...

  6. 【网络编程】之四、socket网络编程例解

    前面说了那么多,现在我们给出4个代码+详解,基于win32平台的socket编程.使用TCP 和 UDP 两种协议. OK,先来看一下TCP服务器和客户端: [cpp] view plaincopy ...

  7. C#网络编程示例(note)

    在.net下进行网络编程其实也相对比较简单,因为在.net类库已经提供了大量封装好的类.在.net下网络编程比较底层的类是System.Net.Sockets.Socket类,这个类提供了丰富的方法和 ...

  8. python服务端编程_python网络编程示例(客户端与服务端)

    client客户端 if __name__ == '__main__': import socket import os sock = socket.socket(socket.AF_INET, so ...

  9. python 网络编程_python网络编程示例(客户端与服务端)

    client客户端 if __name__ == '__main__': import socket import os sock = socket.socket(socket.AF_INET, so ...

最新文章

  1. vue调用后台api_基于ThinkPHP V5+VUE开发的面向API的后台管理系统
  2. 判断某个点是否在不规则图形内
  3. oracle for dotnet
  4. HDR 成像技术学习(三)—— LOFIC
  5. 持续集成工具FinalBuilder使用心得
  6. Redis HyperLogLog 是什么?这些场景使用它~
  7. leetcode 1025 python
  8. Wintel机器代码反逆向(C/C++反逆向破解)
  9. POI 多选下拉菜单(复选框) 导出Excel模板 下拉菜单单选,下拉菜单多选
  10. Ps光速制作文字矢量图
  11. Java 获取PDF数字签名证书信息
  12. Flixel横板游戏制作教程(四)— RandomLevels
  13. WSTMart 国内开源商城系统佼佼者
  14. [蓝桥杯] 三升序列 python解法
  15. canvas显示图片分辨率降低优化
  16. 如何在电脑上打开epub电子书
  17. excel文件导入hive乱码_把数据库数据导出到excel
  18. ECNU ||西班牙馅饼
  19. 连载:大学生求职七大昏招(十七)缺少职业素养(2)
  20. 【python】随机数的生成

热门文章

  1. JAVA计算机存储单元概述及数据类型
  2. JavaSE、JavaEE与Spring的概念和异同点剖析
  3. C++11:move移动语义
  4. 【代码示例】 一个简单的Java死锁
  5. 通过 SSH 连接到 VMware NAT 模式下的 Ubuntu 虚拟机环境
  6. Servlet入门篇(GenericServlet 类 - HttpServlet 类 -ServletConfig 接口 - HttpServletRequest 接口……)
  7. 运用HashMap和ArrayList打造一个简单的带文件的控制台学生管理系统(附上类及类方法的思维导图+控制台运行界面截图+源代码)
  8. python加颜色_python如何给指定的词语加上颜色,并写入Excel文档?
  9. 启明云端分享| SSD201 / SSD202D 在IP广播的应用
  10. Arduino IDE 如何添加 ESP32 开发板?