zoukankan      html  css  js  c++  java
  • boost::asio keepalive


     /*
      * File:   TcpServer.h
      * Author: jtedesco
      *
      * Created on May 26, 2011, 12:33 PM
      */
     
     #ifndef TCPSERVER_H
     #define TCPSERVER_H
     
     #include<set>
     
     #include "Tcp.h"
     #include "Server.h"
     #include "Logger.h"
     
     using boost::asio::ip::tcp;
     using std::set;
     
     class TcpServer: public Tcp, public Server
     {
     
         public:
     
             TcpServer(int port, boost::asio::io_service & io_service);
     
             TcpServer(int port, boost::asio::io_service & io_service, map<string, string> options);
     
             virtual ~TcpServer();
     
             virtual void start_listening();
     
             virtual void shutdown();
     
             virtual int get_port();
     
             FB_JSAPI_EVENT(disconnect, 1, (const string &));
     
             FB_JSAPI_EVENT(connect, 0, ());
     
         protected:
     
     
             void receive_handler(const boost::system::error_code & error_code, std::size_t bytesTransferred,
                     boost::shared_ptr<tcp::socket> connection, string host, int port);
     
             virtual void fire_error_event(const string & message);
     
             virtual void fire_disconnect_event(const string & message);
     
             virtual void fire_data_event(const string data, boost::shared_ptr<tcp::socket> connection);
     
             virtual void close();
     
         private:
     
             void init();
     
             void init_socket(boost::shared_ptr<tcp::socket> connection);
     
             TcpServer(const TcpServer &other);
     
             void accept_handler(const boost::system::error_code & error_code, boost::shared_ptr<tcp::socket> connection, string host, int port);
     
             boost::shared_ptr<tcp::acceptor> acceptor;
             
             set<boost::shared_ptr<tcp::socket> > connections;
     };
     
     #endif  /* TCPSERVER_H */
     




         /*
      * File:   TcpServer.cpp
      * Author: jtedesco
      *
      * Created on May 26, 2011, 12:33 PM
      */
     
     #include "TcpServer.h"
     
     TcpServer::TcpServer(int port, boost::asio::io_service & io_service) :
         Tcp("SERVER", port, io_service)
     {
         init();
     }
     
     TcpServer::TcpServer(int port, boost::asio::io_service & io_service, map<string, string> options) :
         Tcp("SERVER", port, io_service)
     {
         parse_args(options);
         init();
     }
     
     TcpServer::~TcpServer()
     {
         close();
     }
     
     void TcpServer::close()
     {
         // Shutdown the IO service, cancel any transfers on the socket, and close the socket
         waiting_to_shutdown = true;
     
         set<boost::shared_ptr<tcp::socket> >::iterator it;
         for(it = connections.begin(); it != connections.end(); it++)
         {
             try
             {
                 if((*it) && (*it).get() && (*it)->is_open())
                 {
                     (*it)->close();
                 }
             }
             catch(boost::system::error_code &e)
             {
                 Logger::warn("Error in TcpServer deconstructor: " + e.message(), port, host);
             }
             catch(std::exception &er)
             {
                 Logger::warn("Error in TcpServer deconstructor: " + std::string(er.what()), port, host);
             }
             catch(...)
             {
                 Logger::warn("Error occured that could not be caught");
             }
         }
     
         connections.clear();
     
         if (acceptor && acceptor->is_open())
         {
             acceptor->close();
         }
         else
         {
             // Don't fire an error, otherwise the plugin will crash
             string message("Could not cleanly shut down acceptor in TCP server, desctructing anyways");
             Logger::warn(message, port, host);
         }
     }
     
     void TcpServer::init()
     {
         // Bind the acceptor to the correct port & set the options on this acceptor
         try
         {
             if (using_ipv6 && *using_ipv6)
             {
                 acceptor = boost::shared_ptr<tcp::acceptor>(new tcp::acceptor(io_service, tcp::endpoint(tcp::v6(), port)));
             }
             else
             {
                 acceptor = boost::shared_ptr<tcp::acceptor>(new tcp::acceptor(io_service, tcp::endpoint(tcp::v4(), port)));
             }
         }
         catch (boost::system::system_error &e)
         {
             // Catch this error, and fail gracefully
             string message(string("Caught error initializing TCP server: '") + e.what() + "'");
             Logger::error(message, port, host);
     
             // Stop this server from ever doing anything again
             failed = true;
         }
     
         // Check that acceptor was created successfully
         if (!acceptor.get())
         {
             // Fail gracefully and stop this server from ever doing anything again
             string message("Failed to initialized TCP server acceptor");
             Logger::error(message, port, host);
             failed = true;
         }
     }
     
     void TcpServer::init_socket(boost::shared_ptr<tcp::socket> connection)
     {
         // Set the socket options for this client's TCP socket
         if (do_not_route)
         {
             boost::asio::socket_base::do_not_route option(*do_not_route);
             connection->set_option(option);
         }
     
         // Toggle keep alive (enabled/disabled)
         if (keep_alive)
         {
             boost::asio::socket_base::keep_alive option(*keep_alive);
             connection->set_option(option);
         }
         if (no_delay)
         {
             boost::asio::ip::tcp::no_delay option(*no_delay);
             connection->set_option(option);
         }
     
         if (keep_alive_timeout)
         {
             // Set the TCP keep-alive timeout - ignores return value
             set_tcp_keepalive(connection);
         }
     }
     
     void socket_deallocate(tcp::socket * socket)
     {
         // may already have been deallocated
         if(!socket) return;
     
         try
         {
             if(socket && socket->is_open())
             {
                 //s->shutdown(s->shutdown_both);
                 socket->close();
             }
         }
         catch(boost::system::error_code &e)
         {
             Logger::error("socket deallocate: " + e.message());
         }
         catch(std::exception &er)
         {
             Logger::error("socket deallocate: " + std::string(er.what()));
         }
     
         delete socket;
         socket = 0;
     }
     
     void TcpServer::start_listening()
     {
         if(failed)
         {
             // Log & fire an error
             string message("Trying to start the server listening, but the server has permanently failed!");
             Logger::error(message, port, host);
         }
     
         // Log listening
         Logger::info("TCP server about to start listening for incoming connections on port "
                 + boost::lexical_cast<string>(port), port, host);
     
         // Prepare to accept a new connection and asynchronously accept new incoming connections
         boost::shared_ptr < tcp::socket > connection(new tcp::socket(io_service), socket_deallocate);
         connections.insert(connection);
     
         // Try to accept any new connection
         if(acceptor.get())
         {
             acceptor->async_accept(*connection, boost::bind(&TcpServer::accept_handler, this, _1, connection, host, port));
         }
         else
         {
             // Fail gracefully and stop this server from ever doing anything again
             string message("TCP server failed to accept, acceptor invalid");
             Logger::error(message, port, host);
             failed = true;
             return;
         }
     
         // Callback acknowledging that the server has opened
         fire_open();
     }
     
     void TcpServer::shutdown()
     {
         if(!failed)
         {
             waiting_to_shutdown = true;
             if (active_jobs == 0)
             {
                 fire_close();
                 close();
             }
         }
         else
         {
             // Log & fire an error
             string message("Trying to shutdown the TCP server, but the server has permanently failed!");
             Logger::error(message, port, host);
         }
     }
     
     void TcpServer::accept_handler(const boost::system::error_code & error_code, boost::shared_ptr<tcp::socket> connection, string host, int port)
     {
         // Log error & return if there is an error
         if (error_code)
         {
             // Check for disconnection errors
             std::set<boost::system::error_code>::iterator find_result = disconnect_errors.find(error_code);
             if (find_result != disconnect_errors.end())
             {
                 if (error_code == boost::asio::error::operation_aborted)
                 {
                     // If we're waiting to shutdown, this is part of the normal process
                     if(waiting_to_shutdown)
                     {
                         Logger::info("TCP server stopped listening for new connections", port, host);
                     }
                     else
                     {
                         Logger::warn("TCP accept was aborted", port, host);
                     }
                 }
                 else
                 {
                     string message("TCP accept failed, disconnected: '" + error_code.message() + "'");
                     Logger::warn(message, port, host);
                     fire_disconnect(message);
                 }
                 return;
             }
     
             string message("Error accepting incoming connection: '" + error_code.message() + "'");
             Logger::error(message, port, host);
             fire_error(message);
             return;
         }
     
         // Initialize the socket options before we start using it
         init_socket(connection);
     
         // Log that we've successfully accepted a new connection, and fire the 'onconnect' event
         string message("TCP server accepted new connection from " + connection->remote_endpoint().address().to_string() + " port "
                 + boost::lexical_cast<string>(connection->remote_endpoint().port()));
         Logger::info(message, port, host);
         fire_connect();
     
         if (connection.get())
             connection->async_receive(boost::asio::buffer(receive_buffer),
                     boost::bind(&TcpServer::receive_handler, this, _1, _2, connection, host, port));
     
         // Start listening for new connections, if we're not waiting to close
         if (!waiting_to_shutdown)
         {
             start_listening();
         }
     }
     
     
     void TcpServer::receive_handler(const boost::system::error_code & error_code, std::size_t bytesTransferred,
             boost::shared_ptr<tcp::socket> connection, string host, int port)
     {
         Tcp::receive_handler(error_code, bytesTransferred, connection, host, port);
     
         if(connection && connection.get() && !connection->is_open())
             connections.erase(connection);
     }
     
     int TcpServer::get_port()
     {
         return port;
     }
     
     void TcpServer::fire_error_event(const string & message)
     {
         fire_error(message);
     }
     
     void TcpServer::fire_disconnect_event(const string & message)
     {
         fire_disconnect(message);
     }
     
     void TcpServer::fire_data_event(const string data, boost::shared_ptr<tcp::socket> connection)
     {
         fire_data(boost::make_shared<TcpEvent>(this, connection, data));
     }

  • 相关阅读:
    三(奇数)等分两者中间有间隔,两端没间隔
    网易云音乐基于 Flink + Kafka 的实时数仓建设实践
    【电商知识】关于电商定价的几个策略
    硬核!15张图解Redis为什么这么快
    用户画像实践:神策标签生产引擎架构
    数据产品实战(二):ABTest平台
    R代码|基于特征重要性的特征排序代码
    R代码|K均值算法R语言代码
    一文了解R语言数据分析 ----主成分分析
    全网最全 | MySQL EXPLAIN 完全解读
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318610.html
Copyright © 2011-2022 走看看