程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Muduo 網絡編程示例(四)Twisted Finger

Muduo 網絡編程示例(四)Twisted Finger

編輯:關於C++

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.

冒煙測試過關。

查看本欄目

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved