深入应用c++11 随书代码

代码并未在作者github上提供

将书中代码敲至vc 并调试运行 依赖BOOST库 

编译环境vs2015 boost1.59

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

#include "stdafx.h"
#include <boost/thread.hpp>
#include <thread>
#include <string>
#include "../Common/RWHandler.h"

class Connector
{
public:
	Connector(io_service& ios, const string& strIp, short port) :m_ios(ios), m_socket(ios),
		m_serverAddr(tcp::endpoint(address::from_string(strIp), port)), m_isConnected(false),
		m_chkThread(nullptr)
	{
		CreateEventHandler(ios);
	}
	~Connector(){}
	bool Start()
	{
		m_eventHandler->GetSocket().async_connect(m_serverAddr, [this](const boost::system::error_code& error)
		{
			if (error)
			{
				HandleConnectError(error);
				return;
			}
			cout << "connect ok" << endl;
			m_isConnected = true;
			m_eventHandler->HandleRead();
		});
		boost::this_thread::sleep(boost::posix_time::seconds(1));
		return m_isConnected;
	}

	bool IsConnected()const
	{
		return m_isConnected;
	}

	void Send(char* data, int len)
	{
		if (!m_isConnected)
			return;
		m_eventHandler->HandleWrite(data,len);
	}

	void AsyncSend(char* data, int len)
	{
		if (!m_isConnected)
			return;
		//m_eventHandler->HandleAsyncWrite(data, len);
		m_eventHandler->HandleWrite(data, len);
	}
private:
	void CreateEventHandler(io_service& ios)
	{
		m_eventHandler = std::make_shared<RWHandler>(ios);
		m_eventHandler->SetCallBackError([this](int connid) { HandleRWError(connid); });
	}

	void CheckConnect()
	{
		if (m_chkThread != nullptr)
			return;
		m_chkThread = std::make_shared<std::thread>([this]
		{
			while (true)
			{
				if (!IsConnected())
					Start();
				boost::this_thread::sleep(boost::posix_time::seconds(1));
			}
		});
	}

	void HandleConnectError(const boost::system::error_code& error)
	{
		m_isConnected = false;
		cout << error.message() << endl;
		m_eventHandler->CloseSocket();
		CheckConnect();
	}

	void HandleRWError(int connid)
	{
		m_isConnected = false;
		CheckConnect();
	}
private:
	io_service& m_ios;
	tcp::socket m_socket;

	tcp::endpoint m_serverAddr;

	std::shared_ptr<RWHandler> m_eventHandler;
	bool m_isConnected;
	std::shared_ptr<std::thread> m_chkThread;
};

int main()
{
	io_service ios;
	boost::asio::io_service::work work(ios);
	boost::thread thd([&ios] {ios.run(); });

	Connector conn(ios, "127.0.0.1", 9900);
	conn.Start();
	std::string str;
	if (!conn.IsConnected())
	{
		cin >> str;
		return -1;
	}

	const int len = 512;
	char line[len] = "";

	while (cin >> str)
	{
		char header[HEAD_LEN] = {};
		int totalLen = str.length() + 1 + HEAD_LEN;
		std::sprintf(header, "%d", totalLen);
		memcpy(line, header, HEAD_LEN);
		memcpy(line + HEAD_LEN, str.c_str(), str.length() + 1);
		conn.Send(line, totalLen);

	}

    return 0;
}

  

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

#include "stdafx.h"
#include "../Common/RWHandler.h"
#include "../Common/Message.h"

#include <boost/asio/buffer.hpp>
#include <unordered_map>
#include <numeric>

const int MaxConnectionNum = 65536;
const int MaxRecvSize = 65536;
class Server {
public:
	Server(io_service& ios, short port) :m_ios(ios), m_acceptor(ios, tcp::endpoint(tcp::v4(), port)),
		m_connIdPool(MaxConnectionNum)
	{
		m_connIdPool.resize(MaxConnectionNum);
		std::iota(m_connIdPool.begin(), m_connIdPool.end(), 1);
	}

	~Server(){}

	void Accept()
	{
		cout << "Start listening " << endl;
		std::shared_ptr<RWHandler> handler = CreateHandler();

		m_acceptor.async_accept(handler->GetSocket(), [this, handler](const boost::system::error_code& error)
		{
			if (error)
			{
				cout << error.value() << " " << error.message() << endl;
				HandleAcpError(handler, error);
				return;
			}
			m_handlers.insert(std::make_pair(handler->GetConnId(),handler));
			cout << "current connect count: " << m_handlers.size() << endl;

			handler->HandleRead();
			Accept();
		});
	}

private:
	void HandleAcpError(std::shared_ptr<RWHandler> eventHandler, const boost::system::error_code& error)
	{
		cout << "Error,error reason: " << error.value() << error.message() << endl;
		eventHandler->CloseSocket();
		StopAccept();
	}

	void StopAccept()
	{
		boost::system::error_code ec;
		m_acceptor.cancel(ec);
		m_acceptor.close(ec);
		m_ios.stop();
	}

	std::shared_ptr<RWHandler> CreateHandler()
	{
		int connId = m_connIdPool.front();
		m_connIdPool.pop_front();
		std::shared_ptr<RWHandler> handler = std::make_shared<RWHandler>(m_ios);
		handler->SetConnId(connId);
		handler->SetCallBackError([this](int connId)
		{
			RecyclConnid(connId);
		});
		return handler;
	}

	void RecyclConnid(int connId)
	{
		auto it = m_handlers.find(connId);
		if (it != m_handlers.end())
			m_handlers.erase(it);
		//==
		cout << "current connect count: " << m_handlers.size() << endl;
		m_connIdPool.push_back(connId);
	}
private:
	io_service& m_ios;
	tcp::acceptor m_acceptor;
	std::unordered_map<int, std::shared_ptr<RWHandler>> m_handlers;
	list<int> m_connIdPool;

};


int main()
{
	io_service ios;

	Server server(ios, 9900);
	server.Accept();
	ios.run();

    return 0;
}

  

#pragma once

class Message {
public:
	enum { header_length = 4 };
	enum { max_body_length = 512 };

	Message() :body_length_(0){ }

	const char* data() const { return data_; }

	char* data() { return data_; }

	size_t length()const { return header_length + body_length_; }

	const char* body()const { return data_ + header_length; }

	char* body() { return data_ + header_length; }

	size_t body_length()const { return body_length_; }

	void body_length(size_t new_length)
	{
		body_length_ = new_length;
		if (body_length_ > max_body_length)
			body_length_ = max_body_length;
	}

	bool decode_header()
	{
		char header[header_length + 1] = "";
		std::strncat(header, data_, header_length);
		body_length_ = std::atoi(header) - header_length;
		if (body_length_ > max_body_length)
		{
			body_length_ = 0;
			return false;
		}
		return true;
	}

	void encode_header()
	{
		char header[header_length + 1] = "";
		std::sprintf(header,"%4d",body_length_);
		std::memcpy(data_,header,header_length);
	}
private:
	char data_[header_length + max_body_length];
	std::size_t body_length_;
};

  

#pragma once
#include <array>
#include <functional>
#include <iostream>

using namespace std;

#include <boost/asio.hpp>
using namespace boost::asio;
using namespace boost::asio::ip;
using namespace boost;

const int MAX_IP_PACK_SIZE = 65536;
const int HEAD_LEN = 4;

class RWHandler {
public:
	RWHandler(io_service& ios) :m_sock(ios) {}
	~RWHandler(){}
	void HandleRead() {
		async_read(m_sock, buffer(m_buff), transfer_at_least(HEAD_LEN), [this](const boost::system::error_code& ec,
			size_t size) {
			if (ec != nullptr)
			{
				HandleError(ec);
				return;
			}
			cout << m_buff.data() + HEAD_LEN << endl;
			HandleRead();
		});
	}

	void HandleWrite(char* data, int len)
	{
		boost::system::error_code ec;
		write(m_sock, buffer(data, len), ec);
		if (ec != nullptr)
			HandleError(ec);
	}

	tcp::socket& GetSocket() { return m_sock; }

	void CloseSocket()
	{
		boost::system::error_code ec;
		m_sock.shutdown(tcp::socket::shutdown_send, ec);
		m_sock.close(ec);
	}

	void SetConnId(int connId) { m_connId = connId; }

	int GetConnId()const { return m_connId; }

	template<typename F>void SetCallBackError(F f) { m_callbackError = f; }

private:
	void HandleError(const boost::system::error_code& ec)
	{
		CloseSocket();
		cout << ec.message() << endl;
		if (m_callbackError)
			m_callbackError(m_connId);
	}

private:
	tcp::socket m_sock;
	std::array<char, MAX_IP_PACK_SIZE> m_buff;
	int m_connId;
	std::function<void(int)> m_callbackError;
};

  

posted on 2016-03-06 22:16  itdef  阅读(722)  评论(0编辑  收藏  举报

导航