boost完全开发指南第12章-并发编程 1 (采用boost-asio库封装的tcp_server)


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
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值