Muduo网络编程示例之四:Twisted Finger
1 拒绝连接
什么都不做,程序空等。finger01.cc1: #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.cc1: #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 读取用户名,然后断开连接
如果读到一行以 结尾的消息,就断开连接。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. 读取用户名、输出错误信息、然后断开连接
如果读到一行以 结尾的消息,就发送一条出错信息,然后断开连接。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 "); 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) + " "); 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.cc1: 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) + " "); 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语言 ,