Boost: ASIO connection management 5

Source: Internet
Author: User

Let's take a look at the elegant exit, but there are still some imperfections. When receiving the exit signal, io_service is directly disabled, instead of closing all connections and then exiting. In fact, three things should be done in order:

1. reject new TCP connections

2. Close all existing connections

3. Disable io_service

1 is simple. You only need to call acceptor _. Close () once.

2. Each connection class should provide a closesocket method, which internally calls socket. Close (). At the same time, it needs to centrally manage all the connection objects in one place. Therefore, you can design a connections class that contains a lot of shared_ptr <connection>.

3. Finally, call the close method of io_service.

Now code refactoring is a bit complicated. In addition, because two classes are involved in pointing to each other, they have to write separate files.

First, modify the connection class and provide a closesocket method. In addition, read a character. If it is 'A', continue reading. If it is not a, close the connection.

Header file:

#ifndef CONNECTION_H#defineCONNECTION_H#include <vector>#include <boost/asio.hpp>#include <boost/enable_shared_from_this.hpp>using namespace boost;using namespace boost::asio;using ip::tcp;using namespace std;using boost::system::error_code;class Connections;       class Connection: public boost::enable_shared_from_this<Connection> {public:    Connection(io_service& s, Connections& cons);        ~Connection();        void StartWork();        void CloseSocket();        void AfterReadChar(error_code const& ec);    public:    tcp::socket socket;    private:    vector<char> read_buffer_;    Connections& cons_;};#endif/* CONNECTION_H */

Implementation Code:

#include "Connection.h"#include <boost/bind.hpp>#include "Connections.h"Connection::Connection(io_service& s, Connections& cons): socket(s), read_buffer_(1, 0), cons_(cons) {}Connection::~Connection() {    cout << "~Connection" << endl;}void Connection::StartWork() {    cout << "the new connection object is starting now." << endl;    async_read(socket, buffer(read_buffer_),            boost::bind(&Connection::AfterReadChar, shared_from_this(), _1));}void Connection::CloseSocket() {    cout << "closing the socket" << endl;    socket.shutdown(tcp::socket::shutdown_both);    socket.close();}void Connection::AfterReadChar(error_code const& ec) {    if (ec) {        cout << ec.message() << endl;        return;    }    char x = read_buffer_[0];    if (x == 'a') {        cout << "correct data received" << endl;        async_read(socket, buffer(read_buffer_),                boost::bind(&Connection::AfterReadChar, shared_from_this(), _1));    } else {        cout << "wrong data received, char is:" << (int) x << endl;        CloseSocket();        cons_.Remove(shared_from_this());    }}

The connections reference is saved in the connection. When an error character is read, the socket is closed and then deleted from connections.

Now let's look at the connections code and use set to save all connections internally, because my goal is to support at least several thousand connections. The vector is obviously not suitable, and the set with tree structure can be at the top.

Header file:

#ifndef CONNECTIONS_H#defineCONNECTIONS_H#include <set>#include <algorithm>#include <boost/shared_array.hpp>using namespace std;using namespace boost;#include "Connection.h"class Connections {public:    void Add(shared_ptr<Connection>& con);        void Remove(shared_ptr<Connection> con);        void CloseAll();    private:    set<shared_ptr<Connection> > values_;};

Implementation Code:

#include "Connections.h"#include <boost/bind.hpp>void Connections::Add(shared_ptr<Connection>& con) {    values_.insert(con);    cout << "the number of connections is: " << values_.size() << endl;}void Connections::Remove(shared_ptr<Connection> con) {    values_.erase(con);}void Connections::CloseAll() {    for_each(values_.begin(), values_.end(), boost::bind(&Connection::CloseSocket, _1));    values_.clear();}

Connections provides methods to add, delete, and close all connections. Server objects use add and closeall, and remove is used by connection objects.

Now let's take a look at the server and main function code:

#include <cstdlib>#include <boost/asio.hpp>#include <boost/bind.hpp>#include <iostream>#include <vector>#include <algorithm>#include "Connection.h"#include "Connections.h"using namespace boost;using namespace boost::asio;using ip::tcp;using namespace std;using boost::system::error_code;class Server {public:    Server(io_service & s, tcp::endpoint const& listen_endpoint)    : io_(s), signals_(s), acceptor_(s, listen_endpoint) {        signals_.add(SIGINT);        signals_.add(SIGTERM);#if defined(SIGQUIT)        signals_.add(SIGQUIT);#endif        signals_.async_wait(boost::bind(&Server::Stop, this));        shared_ptr<Connection> c(new Connection(io_, cons_));                acceptor_.async_accept(c->socket,                boost::bind(&Server::AfterAccept, this, c, _1));    }    void Run() {        io_.run();    }    void AfterAccept(shared_ptr<Connection>& c, error_code const& ec) {        // Check whether the server was stopped by a signal before this completion        // handler had a chance to run.        if (!acceptor_.is_open()) {            return;        }                if (!ec) {            cons_.Add(c);            c->StartWork();            shared_ptr<Connection> c2(new Connection(io_, cons_));            acceptor_.async_accept(c2->socket,                    boost::bind(&Server::AfterAccept, this, c2, _1));        }    }private:    void Stop() {        cout << "stopping" << endl;        acceptor_.close();        cons_.CloseAll();        io_.stop();    }private:    io_service& io_;    boost::asio::signal_set signals_;    tcp::acceptor acceptor_;    Connections cons_;};int main(int argc, char** argv) {    io_service s;    tcp::endpoint listen_endpoint(tcp::v4(), 8888);    Server server(s, listen_endpoint);    server.Run();    return 0;}

Once the connection is accepted, a new connection is added to connections. When the signal is closed, all connections are closed.

The next section will be tested with a newlisp program, proving that the program is reliable.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.