现在的位置: 首页 > 综合 > 正文

Asio实现的实用echo server

2013年10月10日 ⁄ 综合 ⁄ 共 5506字 ⁄ 字号 评论关闭
 关于echo的简单server,几乎多得发指,但大部分都没有提供类似粘包,定时器,安全退出等开发中的
常用机制,换句话说,为了echo而echo,借鉴价值大打折扣,毕竟我们平时的工作不可能这么简单。这几天研究了下asio,感觉不错,boost接纳
asio后,在服务器开发领域是不是该得到重视呢:),还是贴代码吧,有注释

// asio.cpp : 定义控制台应用程序的入口点。
//

#include 
"stdafx.h"

//禁止boost自动链接静态库
#define BOOST_ALL_DYN_LINK

#include 
<cstdlib>
#include 
<iostream>
#include 
<boost/bind.hpp>
#include 
<boost/asio.hpp>
#include 
<boost/lexical_cast.hpp>

using boost::asio::ip::tcp;

class session
{
public:
    session(boost::asio::io_service
& io_service)
        : socket_(io_service),
        timer_(io_service),
        exit_flag_(
false)        
    
{
        std::cout 
<< "session born/n";
    }

    
~session()
    
{
        std::cout << "session destroy/n";
    }


    tcp::socket
& socket()
    
{
        
return socket_;
    }


    
void start()
    
{//async_receive,async_read_some
        /*
        socket_.async_receive(boost::asio::buffer(data_, max_length),
            boost::bind(&session::handle_read, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
            
*/

        
//读到4个字节才返回,可以和上面注释的sync_receive比较
        boost::asio::async_read(socket_,
            boost::asio::buffer(data_, 
4),
            boost::bind(
&session::handle_read, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
            ));
        
        size_t cancelcnt 
= timer_.expires_from_now(boost::posix_time::seconds(10));
        
//@return The number of asynchronous operations that were cancelled;第一次启动定时器
        std::cout << "timer canceled count is = " << cancelcnt << std::endl;
        
        timer_.async_wait(boost::bind(
&session::handle_timeout,this,
            boost::asio::placeholders::error));        
    }


protected:

    
void handle_read(const boost::system::error_code& error,
        size_t bytes_transferred)
    
{//可以考虑复杂应用,如:如何集成数据库操作等
        
        
if (!error)
        
{
            
if (bytes_transferred < header_lenght)
            
{//处理正常退出
                std::cout << "need close/n";
                
this->handle_exit();
                delete 
this;
                
return;
            }

            
else if (bytes_transferred == header_lenght)//header
            {
                data_[bytes_transferred] 
= '/0';
                std::cout 
<< "packet len = " << data_ << std::endl;
                
int bodylen = boost::lexical_cast<int>(data_);
                boost::asio::async_read(socket_,
                    boost::asio::buffer(data_,bodylen),
                    boost::bind(
&session::handle_read,this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));    
                
                
return;
            }

            
else
            
{//读到了bodylen长度才返回,如果由于网络原因等导致长时间没有读全,则上面的定时器会做超时处理
                if (bytes_transferred < max_length)
                
{
                    data_[bytes_transferred] 
= '/0';
                }

                std::cout 
<< data_ << std::endl;
                boost::asio::async_write(socket_,
                    boost::asio::buffer(data_, bytes_transferred),
                    boost::bind(
&session::handle_write, this,
                    boost::asio::placeholders::error));
                
//                 size_t cancelcnt = timer_.expires_from_now(boost::posix_time::seconds(10));
//                 std::cout << "timer canceled count is = " << cancelcnt << std::endl;
//                 timer_.async_wait(boost::bind(&session::handle_timeout,this,
//                      boost::asio::placeholders::error));                
                socket_.async_receive(boost::asio::buffer(data_, 1),
                    boost::bind(
&session::handle_read, this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
//发起异步读操作,以便后面正常退出
             }
            
        }

        
else
        
{
            std::cout 
<< "error = " << error << "   bytes_transferred = " << bytes_transferred << std::endl;
            
this->handle_exit();
            delete 
this;//这句不能放在handle_exit里面,否则问题多多,没找到好的解决方案
        }

    }


    
void handle_write(const boost::system::error_code& error)
    
{
        
if (!error)
        
{
            std::cout 
<< "handle_write ok/n";    
            
this->handle_exit();
        }

        
else
        
{
            std::cout 
<< "handle_write error/n";
        }
        
        
return;
    }

    
void handle_timeout(const boost::system::error_code& e)
    
{
        
if (e != boost::asio::error::operation_aborted)
        
{
            std::cout 
<< "timeout now./n";    
            
this->handle_exit();
        }

        
else
        
{//被取消
            std::cout << "cancelled now./n";
        }
            
        
return;
    }

    
void handle_exit()
    
{
        std::cout 
<< "enter handle_exit1./n";        
        
if (!exit_flag_)
        
{
            std::cout 
<< "enter handle_exit2./n";
            exit_flag_ 
= true;
            timer_.cancel();
            socket_.close();
            std::cout 
<< "after socket close./n";
            
/*
            Any asynchronous send, receive
            or connect operations will be cancelled immediately, and will complete
            with the boost::asio::error::operation_aborted error
            
*/

            
//delete this;
            return;
        }

        
else
        
{
            
return;
        }

    }


private:
    tcp::socket socket_;    
    boost::asio::deadline_timer timer_;
    
bool exit_flag_;    
    
enum {header_lenght = 4,  max_length = 1024 };
    
char data_[max_length];
}
;

class server
{
public

抱歉!评论已关闭.