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

代码并未在作者github上提供

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

编译环境vs2015 boost1.59

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// 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;
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// 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;
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#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_;
};

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#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   itdef  阅读(738)  评论(0编辑  收藏  举报

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示