2011-08-29 13 views
4

我一直在閱讀很多ASIO示例,但我仍然對如何在應用程序中使用它們感到困惑。基本上,我的服務器端需要接受超過100個連接(客戶端),這部分是通過使用一個線程池(通常每個CPU核心有2〜4個線程)完成的。如何將這個Boost ASIO示例應用到我的應用程序

爲簡單起見,我們假設只有一個連接。

爲了簡單起見,我也想的例子從複製:http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/nonblocking/third_party_lib.cpp

class session 
{ 
public: 
    session(tcp::socket&) 
    bool want_read() const; 
    bool do_read(boost::system::error_code&); 
    bool want_write() const; 
    bool do_write(boost::system::error_code&); 
}; 

class connection : public boost::enable_shared_from_this<connection> 
{ 
public: 
    typedef boost::shared_ptr<connection> pointer; 
    static pointer create(boost::asio::io_service&); 
    tcp::socket& socket(); 
    void start(); 
private: 
    connection(boost::asio::io_service&); 
    void start_operation(); 
    void handle_read(boost::system::error_code); 
    void handle_write(boost::system::error_code); 
} 

class server 
{ 
public: 
    server(boost::asio::io_service&, unsigned short); 
private: 
    void start_accept(); 
    void handle_accept(connection::pointer, const boost::system::error_code&); 
} 

您可以檢查鏈接的完整的類實現。

我想要做的是爲讀/寫操作加入到session類(或者我應該直接把他們connection?)

AsyncRead(buffer, expectedBytesToRead, timeout, handler); 
Read(buffer, expectedBytesToRead, timeout); 
AsyncWrite(buffer, expectedBytesToWrite, timeout, handler); 
Write(buffer, expectedBytesToWrite, timeout); 

我看過很多例子,但它在我看來,很難弄清楚如何使用它們,即在我的應用程序中實現上述4種常用方法。

我想我非常接近我想要的東西,我只是沒有從一個非常簡單的例子開始。我讀了@ boost.org的例子,它們要麼太複雜,以至於無法理解我的項目中的邏輯或者我想要的內容。

+0

您鏈接的'null_buffers'示例顯示如何將asio'io_service'事件循環與已經在套接字上執行'read'和'write'的庫集成。我不清楚你有這個要求。你能澄清你爲什麼要使用'null_buffers'? –

+0

是的。我也很困惑。我這樣做的原因是我想將讀/寫邏輯與'connection'類分開。也許,正如我所說的,我應該把上述4個請求的方法放在'connection'類中(刪除無用的'session'類)?另一個原因是,我有一箇舊類(從舊代碼)進行低級讀/寫操作,所以我將它視爲第三方庫。 –

+2

因爲它是你的代碼我建議你用Asio的'async_read()'和'async_write()'自由函數重寫它。使用'null_buffers'的唯一原因是如果你有遺留代碼或者第三方代碼不可能被改變。 –

回答

0

我會建議保持與套接字在連接類中的所有通信,並儘可能保持通用。

您的選擇幾乎是無限的,你想如何做到這一點。我所做的是將我的「消息處理」類的shared_ptr傳遞給每個新連接,並像您一樣創建一個會話,但我將每個連接的副本傳遞給會話以及所有相關信息。因此,每個單獨會話可以在新消息進入時通知程序,並且我可以在每個會話中存儲任何我想要的內容。

由於您現在將它存儲在某個地方,並且不僅通過回調使智能指針保持活動狀態,所以在連接終止時請注意通知您的會話。

typedef boost::shared_ptr<class Connection> connectionPtr; 

void Server::handle_accept(sessionPtr new_connection, const boost::system::error_code& error) 
{ 
if (!error) 
{ 
    cout << "New connection detected." << endl; 
    string sessionID = misc::generateSessionID(); 
    string IPaddress = new_connection->socket().remote_endpoint().address().to_string(); 
    mSessionManager_->AddSession(new_connection, IPaddress, sessionID); 
    // session manager now has a copy of the connection and 
    // can reference this by the sessioNID or IPAddress 
    new_connection->start(); 

    connectionPtr NEWER_CONNECTION(new Connection(_io_service, _loginList, _mMessageHandlerClass)); 

    cout << "Awaiting next connection..." << endl; 
    acceptor_.async_accept(newer_session->socket(), 
    boost::bind(&Server::handle_accept, this, NEWER_CONNECTION, 
       boost::asio::placeholders::error)); 
} 
else 
{ 
    new_connection.reset(); 
} 

}

這裏只是如何處理消息的例子。顯然總剩餘字節數需要從頭文件中提取,這在示例中並未包含。

void Session::handle_body(const boost::system::error_code& error, size_t bytes_transferred) 
if(!error) 
    { 
     totalBytesRemaining -= bytes_transferred; 

     if (totalBytesRemaining == 0) 
      { 
      if (incompleteToggle = true) 
      { 
       tempMessage+=string(readMsg.body()); 
       messageHandlerClass->Process(sessionID,tempMessage); 
       tempMessage = ""; 
       tempMessageToggle = false; 
      } 
      else 
      { 
       tempMessage += string(readMsg.body()); 
       std::cout << "Incomplete receive: This is our message So far.\n\n" << tempMessage << "\n" << endl; 
       tempMessageToggle = true; 
      } 

     } 

    handle_message(); 
    } 
else 
{ 
    removeSession(); 
} 

所以現在我有從SessionManager類

void SessionManager::listConnectedIP() 
{ 
    for (int x = 0; x < sessionBox.size(); x++) 
    { 
     cout << sessionBox[x]->IPaddress() << endl; 
    } 
} 
void SessionManager::massSendMessage(const std::string &message) 
{ 
    for (int x = 0; x < sessionBox.size(); x++) 
    { 
     sessionBox[x]->connectionPtr->pushMessage(message); 
    } 
} 

以及處理郵件的連接類訪問我的所有會話是這樣的。消息只是保存緩衝區並對頭進行編碼和解碼。這是我在boost示例網站上找到的另一個修改過的類。

void Connection::pushMessage(const string& message) 
{ 
// boost async_write will return instantly, but guarantees to 
// either error or send all requested bytes. 
// there is no need to check if all bytes get sent in the callback. 
    Message writeMsg; 
    writeMsg.body_length(strlen(msg.c_str())); 
    memcpy(writeMsg.body(), msg.c_str(), writeMsg.body_length()); 
    writeMsg.encode_header(); 

    boost::asio::async_write(socket_, boost::asio::buffer(writeMsg.data(), writeMsg.length()), 
    boost::bind(&Session::handle_write, this, boost::asio::placeholders::error, 
    boost::asio::placeholders::bytes_transferred)); 
} 

對不起,如果我的例子不是很好。爲了真正掌握boost :: asio及其示例,您需要了解異步函數和回調函數的工作原理。