开发者

How To Apply This Boost ASIO Example To My Application

开发者 https://www.devze.com 2023-03-31 19:12 出处:网络
I\'ve been reading a lot of ASIO examples, but I\'m still sort of confused on how to use them in my application.

I've been reading a lot of ASIO examples, but I'm still sort of confused on how to use them in my application.

Basically, my server side needs to accept more than 100 connections (clients), this part is done by using a pool of threads (usually, 2~4 threads for each CPU core).

For simplicity, let's just assume there is only one connection.

For simplicity, I would also like to copy the example from: 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&开发者_开发知识库amp;);
}

You can check the link for the complete class implementations.

What I'm trying to do is to add for read/write operations into class session (or should I directly put them in connection?)

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

I did read a lot of examples, but it seems to me that it's very difficult to figure out how to use them, i.e., implement the above 4 common methods in my application.

I guess I'm very close to what I want, I just don't where to start from a very simple example. The example I read @ boost.org, they are either too complicated to figure out the logic or not what I want in my project.


I would suggest keeping all of your communication with the socket in your connection class, keeping it as generic as possible.

Your options are almost limitless on how you want to do it. What I do is pass a shared_ptr of my "Message Handling" class to each new Connection and also create a Session like you do, but I pass a copy of each Connection to the Session and all relevant info as well.. so each individual session can notify the program when a new message comes in, and I can store anything else I want in each Session.

Just be careful about notifying your Sessions when the Connection terminates, since you are now storing it somewhere and not only keeping the smart pointer alive via call-backs.

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();
}

}

Here's just an example of how to handle a message. Obviously totalbytesremaining needs to be extracted from the header, which I didn't include in examples.

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();
}

So now I have access to all my Sessions from the SessionManager class

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);
    }
}

And the Connection class for handling messages is something like this. Message just holds the buffer and encodes and decodes the header. It's another modified class I found on the boost example website.

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));
}

Sorry if my examples aren't very good. To get a real grasp of boost::asio and their examples, you really need to understand how asynchronous functions and callbacks work.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号