1、intdef.hpp
#ifndef __INTDEF_HPP__
#define __INTDEF_HPP__
#include <boost/cstdint.hpp>
using boost::int8_t;
using boost::uint8_t;
using boost::int16_t;
using boost::uint16_t;
using boost::int32_t;
using boost::uint32_t;
using boost::int64_t;
using boost::uint64_t;
typedef boost::uint8_t byte_t;
typedef boost::uint8_t uchar_t;
typedef unsigned short ushort_t;
typedef unsigned int uint_t;
typedef unsigned long ulong_t;
typedef boost::uint16_t word_t;
typedef boost::uint32_t dword_t;
#endif
2、tcp_buffer.hpp
#ifndef __TCP_BUFFER_HPP__
#define __TCP_BUFFER_HPP__
#include <boost/asio.hpp>
#include <boost/config/suffix.hpp>//for static member variants
#include <boost/cast.hpp>
class tcp_buffer
{
public:
typedef std::size_t size_type;
typedef boost::asio::streambuf streambuf_type;
typedef streambuf_type::const_buffers_type const_buffers_type;
typedef streambuf_type::mutable_buffers_type mutable_buffers_type;
private:
BOOST_STATIC_CONSTANT(size_type, BUF_SIZE=1024);
streambuf_type m_buf;
public:
//
// read functions
//
//use to recv n bytes
mutable_buffers_type prepare(size_type n = BUF_SIZE)
{
return m_buf.prepare(n);
}
//get the recieved n bytes data
void retrieve(size_type n)
{
m_buf.commit(n);
}
//get the bytes count of readable data
size_type size() const
{
return m_buf.size();
}
//check readable bytes
const char* peek() const
{
return boost::asio::buffer_cast<const char*> (m_buf.data());
}
/*******************************
// write functions
/*******************************/
/* write data to m_buf */
void append(const void * data, size_type len)
{
m_buf.sputn(static_cast<const char*>(data),
boost::numeric_cast<std::streamsize>(len));//use numeric_cast
}
const_buffers_type data() const{
return m_buf.data();
}
//consume
void consume(size_type n)
{
m_buf.consume(n);
}
};
#endif
3、tcp_session.h
#ifndef __TCP_SESSION_HPP__
#define __TCP_SESSION_HPP__
#include "tcp_buffer.hpp"
#include <boost/smart_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
class tcp_session : public boost::enable_shared_from_this<tcp_session>
{
public:
typedef boost::asio::ip::tcp::socket socket_type;
typedef boost::asio::io_service ios_type;
typedef tcp_buffer buffer_type;
public:
tcp_session(ios_type& ios);
socket_type& get_socket();
ios_type& get_io_service();
buffer_type& get_read_buf();
buffer_type& get_write_buf();
void start();
void close();
void write();//async send
void write(const void* data, std::size_t len);
private:
void read();
void handle_read(const boost::system::error_code& ec, size_t bytes_transferred);
void handle_write(const boost::system::error_code& ec, size_t bytes_transferred);
private:
socket_type m_socket;
buffer_type m_read_buf;//read buffer
buffer_type m_write_buf;//write buffer
};
typedef boost::shared_ptr<tcp_session> tcp_session_ptr;// 共享指针定义
#endif
tcp_session.cpp
#include "tcp_session.h"
#include <iostream>
#include <string>
using namespace std;
#include <boost/bind.hpp>
using namespace boost;
using namespace boost::asio;
tcp_session::tcp_session(ios_type& ios):m_socket(ios)
{
}
tcp_session::socket_type& tcp_session::get_socket()
{
return m_socket;
}
tcp_session::ios_type& tcp_session::get_io_service()
{
return m_socket.get_io_service();
}
tcp_session::buffer_type& tcp_session::get_read_buf()
{
return m_read_buf;
}
tcp_session::buffer_type& tcp_session::get_write_buf()
{
return m_write_buf;
}
void tcp_session::start()
{
std::cout<<"Session start"<<std::endl;
read();
}
void tcp_session::close()
{
boost::system::error_code ignored_ec;
m_socket.shutdown(ip::tcp::socket::shutdown_both, ignored_ec);
m_socket.close(ignored_ec);
}
void tcp_session::read()
{
m_socket.async_read_some(m_read_buf.prepare(),
bind(&tcp_session::handle_read, shared_from_this(),
placeholders::error, placeholders::bytes_transferred ));
}
void tcp_session::handle_read(const system::error_code& error, size_t bytes_transferred)
{
if (error)
{
close();
return;
}
std::cout<<"read size:"<<bytes_transferred<<std::endl;
m_read_buf.retrieve(bytes_transferred);
std::cout<<std::string(m_read_buf.peek(), bytes_transferred)<<std::endl;
write(m_read_buf.peek(), bytes_transferred);
m_read_buf.consume(bytes_transferred);
read();
}
void tcp_session::write(const void* data, std::size_t len)
{
cout<<"write:"<<len<<endl;
cout<<static_cast<const char*> (data)<<endl;
m_write_buf.append(data, len);
write();
}
void tcp_session::write()
{
m_socket.async_write_some(m_write_buf.data(),
bind(&tcp_session::handle_write, shared_from_this(),
placeholders::error,
placeholders::bytes_transferred));
}
void tcp_session::handle_write(const boost::system::error_code& ec, size_t bytes_transferred)
{
if (ec)
{
close();
return;
}
m_write_buf.consume(bytes_transferred);
cout<<"write complete"<<endl;
}
4、tcp_server.h
#ifndef __TCP_SERVER_HPP__
#define __TCP_SERVER_HPP__
#include "intdef.hpp"
#include "tcp_session.h"
#include "io_service_pool.hpp"
class tcp_server
{
public:
typedef io_service_pool::ios_type ios_type;
typedef boost::asio::ip::tcp::acceptor accept_type;
tcp_server(ushort_t port, int n = 1);
void start();
void run();
void start_accept();
void handle_accept(const boost::system::error_code& ec, tcp_session_ptr session_ptr);
private:
io_service_pool m_ios_pool;
accept_type m_acceptor;
};
#endif
tcp_server.cpp
#include "tcp_server.h"
#include <boost/bind.hpp>
#include <boost/functional/factory.hpp>
using namespace boost;
using namespace boost::asio;
tcp_server::tcp_server(ushort_t port, int n): m_ios_pool(n),
m_acceptor(m_ios_pool.get(),ip::tcp::endpoint(ip::tcp::v4(),port))
{
start_accept();
}
void tcp_server::start_accept()
{
tcp_session_ptr session = factory<tcp_session_ptr>()(m_ios_pool.get());//factory<func_return_type>()(func_param)
m_acceptor.async_accept(session->get_socket(), bind(&tcp_server::handle_accept, this, placeholders::error, session));
}
void tcp_server::handle_accept(const boost::system::error_code& ec, tcp_session_ptr session_ptr)
{
start_accept();
if (ec)
{
session_ptr->close();
return;
}
session_ptr->start();
}
void tcp_server::start()
{
m_ios_pool.start();//none block mode
}
void tcp_server::run()
{
m_ios_pool.run();//block mode , main thread use join_all to wait all child thread
}