POCO庫中文程式設計參考指南(8)豐富的Socket程式設計

鍾超發表於2012-04-17

POCO庫中文程式設計參考指南(8)豐富的Socket程式設計

  • 作者:柳大·Poechant
  • 部落格:Blog.CSDN.net/Poechant
  • 郵箱:zhongchao.ustc#gmail.com (# -> @)
  • 日期:April 16th, 2012

1 POCO 中的 Socket

POCO 中有 豐富的 Socket 封裝。其繼承關係如下:

Resize icon

本文暫且只介紹 StreamSocket、ServerSocket、DatagramSocket

2 Poco::Net::ServerSocket

ServerSocket 是一個封裝層次比較低(low level)的 Socket,其使用的是 TCP 連線。在實際的 Server 中推薦使用 TCPServer 或 Reactor 框架。下面是例程:

#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/SocketStream.h"
#include "Poco/Net/StreamSocket.h"
#include <iostream>

int main(int argc, char **argv)
{

繫結埠,並開始監聽:

    Poco::Net::ServerSocket srv(12345);

服務主迴圈:

    while (true)
    {

接受連線:

        Poco::Net::StreamSocket streamSocket = srv.acceptConnection();

向 Socket 傳送資料:

        Poco::Net::SocketStream socketStream(streamSocket);
        socketStream << "HTTP/1.0 200 OK\r\n"
                     << "Content-Type: text/html\r\n"
                     << "\r\n"
                     << "<html><head><title>My 1st Web Server</title></head></html>"
                     << std::flush;
    }
    return 0;
}

3 TCPServer 框架

POCO 提供了一個 TCPServer,顧名思義,是一個 TCP 伺服器。準確的說,TCPServer 是一個 Framework,要求使用 ServerSocket 去 accept 連線。並且在將 ServerSocket 轉遞給 TCPServer 之前必須將其設定為監聽模式。

TCPServer 維護一個連線佇列(connection queue)。TCPServer 開啟多個執行緒去從連線佇列中取連線並進行處理,執行緒的數量是動態的,與連線佇列中的連線數有關。

非正常連線會被立即關閉,而不會被插入連線佇列。TCPServer 的主執行緒負責將客戶端發來的請求連線放入連線佇列。

TCPServer 是一個高效的開發框框架,具體詳見《POCO庫中文程式設計參考指南(10)如何使用TCPServer框架?》一文。

4 Poco::Net::DatagramSocket

4.1 UDP Client

#include "Poco/Net/DatagramSocket.h"  
#include "Poco/Net/SocketAddress.h"  
#include "Poco/Timestamp.h"  
#include "Poco/DateTimeFormatter.h"  
#include <string>

int main()
{
    const char* ipaddr = "127.0.0.1";
    Poco::Net::SocketAddress sa("127.0.0.1", 1234);  
    Poco::Net::DatagramSocket dgs;
    dgs.connect(sa); 

    std::string syslogMsg;  
    Poco::Timestamp now;  
    syslogMsg = Poco::DateTimeFormatter::format(now, "<14>%w %f %H:%M:%S Hello,world!");  
    dgs.sendBytes(syslogMsg.data(), syslogMsg.size());  

    return 0;  
}  

不能用:

...
const char* ipaddr = "127.0.0.1";
Poco::Net::SocketAddress sa("127.0.0.1", 1234);  
Poco::Net::DatagramSocket dgs(sa);

std::string syslogMsg;  
Poco::Timestamp now; 
... 

因為 DatagramSocket(SocketAddress) 建構函式是建立一個 DatagramSocket 然後 bind()。而這裡要使用的是 connect()。

4.2 UDP Server

#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/IPAddress.h"
#include <iostream>

int main(int argc, char **argv)
{
    Poco::Net::SocketAddress socketAddress(Poco::Net::IPAddress(), 1234);
    Poco::Net::DatagramSocket datagramSocket(socketAddress);

    char buffer[1024];

    while (true)
    {
        Poco::Net::SocketAddress sender;
        int n = datagramSocket.receiveFrom(buffer, sizeof(buffer) - 1, sender);
        buffer[n] = '\0';
        std::cout << sender.toString() << ": " << buffer << std::endl;
    }

    return 0;
}

5 Reactor 框架

Reactor 框架是利用 Event/Notification 實現的基於 Reactor 設計模式的一個伺服器框架,由於 Event/Notification 存在而支援非同步。

具體詳見本博的另一篇博文《POCO庫中文程式設計參考指南(11)如何使用Reactor框架?》

6 StreamSocket

也是一個 TCP 的 Socket,可以使資料傳輸操作變的簡化,被用在 TCP 伺服器和客戶端。

-

轉載請註明來自柳大的CSDN部落格:Blog.CSDN.net/Poechant

-

相關文章