关于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
常用机制,换句话说,为了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