TCP эхо сервер с бустом asio - PullRequest
       17

TCP эхо сервер с бустом asio

0 голосов
/ 11 сентября 2018

Я пытаюсь сделать tcp echo server с boost asio. Я успешно передал данные строки на сервер от клиента. Но я не могу передать полученные данные от клиента к клиенту. Я не знаю, вызвана ли эта проблема функцией async_write () в коде сервера или функцией async_read () в коде клиента. Я полагаю, что эта проблема вызвана объявлением потока и вызовом их функции, но я не уверен.

Резюме: Я не знаю правильную причину этой проблемы .. Помогите мне, пожалуйста ...

Северный код

#include <iostream>
#include <boost/asio.hpp>
#include <cstring>
#include <cstdlib>
#include <memory>
#include <deque>
#include <list>
#include <set>

using boost::asio::ip::tcp;

typedef std::string echo_message;

class echo_session 
    : public std::enable_shared_from_this<echo_session>
{
public:
    echo_session(tcp::socket socket, std::set<std::shared_ptr<echo_session>>& session_place)
        : socket_(std::move(socket)),
        session_place_(session_place)
    {
        std::cout << "Session Initializing...\n";
        read_msg_ = "Server!";
    }

    void start()
    {
        int se_num=0;
        std::cout << "Session starting...\n";
        session_place_.insert(shared_from_this());  
        for(auto session: session_place_)
        {
            se_num++;
        }
        std::cout << "Session num: " << se_num << std::endl;
        do_read_message();
    }

    void deliver(const echo_message& msg)
    {
        this->write_msg_ = msg;
        do_write();
    }
private:
    void do_read_message()
    {
        auto self(shared_from_this());
        char *read_buffer = new char[128];
        std::cout << "Reading Message...\n";
        boost::asio::async_read(socket_,
            boost::asio::buffer(read_buffer, 128),
            [this, self, read_buffer](boost::system::error_code ec, std::size_t)
            {
                if(!ec)
                {
                    read_msg_ = read_buffer;
                    std::cout << "do_read_message() Message:" << read_msg_ << std::endl;
                    /*
                    /////////////////////////////
                    Used Debugging Part
                    ////////////////////////////
                    std::cout << "Async Read! : ";
                    std::cout << read_msg_ << std::endl;
                    std::cout << "Length:"  << read_msg_.length() << std::endl;
                    */

                    deliver(read_msg_);
                    do_read_message();
                }
                else
                {
                    std::cout << "Async Read Failed!\n";
                    std::cerr << "Error: " << ec.message() << std::endl;
                }
            });
        std::cout << "do_read_message() is returned!\n";
    }

    void do_write()
    {
        auto self(shared_from_this());
        char *read_buffer = new char[sizeof(write_msg_.c_str())];
        memcpy(read_buffer, write_msg_.c_str(), sizeof(write_msg_.c_str()));
        boost::asio::async_write(socket_,
            boost::asio::buffer(read_buffer, sizeof(read_buffer)),
            [this, self, read_buffer](boost::system::error_code ec, std::size_t)
            {
                if(!ec)
                {
                    std::cout << "Message <" << read_buffer << ">Writed!\n";
                    this->write_msg_ = "\0";
                }
                else
                {
                    std::cout << "Write Failed\n";
                }
                std::cout << "do_write lambda returned!\n";
            });
    }
    tcp::socket socket_;
    echo_message read_msg_;
    echo_message write_msg_;
    std::set<std::shared_ptr<echo_session>>& session_place_;
};

class echo_server {
public:
    echo_server(boost::asio::io_context& io_context,
        const tcp::endpoint& endpoint)
        : acceptor_(io_context, endpoint)
    {
        do_accept();
    }
private:
    void do_accept()
    {
        acceptor_.async_accept(
            [this](boost::system::error_code ec, tcp::socket socket)
            {
                if(!ec)
                {
                    std::make_shared<echo_session>(std::move(socket), sessions_)->start();
                    std::cout << "Accept!\n";
                }
                else
                {
                    std::cout << "Accept Failed!\n";
                }

                do_accept();
            });
    }

    tcp::acceptor acceptor_;
    std::set<std::shared_ptr<echo_session>> sessions_;
};

int main(int args, char *argv[])
{

    try
    {
        if( args != 2)
        {
            std::cerr << "Usage: server <port>" << std::endl;
            return 1;
        }

        boost::asio::io_context io_context;

        tcp::endpoint endpoint(tcp::v4(), std::atoi(argv[1]));
        echo_server ex_server(io_context, endpoint);

        io_context.run();
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    return 0;
}

код клиента

#include <iostream>
#include <deque>
#include <thread>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

typedef std::string echo_message;

class echo_client {
public:
    echo_client(boost::asio::io_context& io_context,
        const tcp::resolver::results_type& endpoints)
        : io_context_(io_context),
        socket_(io_context)
    {
        do_connect(endpoints);
    }

    void write(const std::string string)
    {
        boost::asio::post(io_context_,
            [this, string]()
            {
                //std::cout << "Post Success!\n";
                do_write(string);
            });
    }

    void close()
    {
        boost::asio::post(io_context_,
            [this]()
            {
                std::cout << "Close Success!\n";
                socket_.close();
            });
    }
private:
    void do_connect(const tcp::resolver::results_type& endpoints)
    {
        boost::asio::async_connect(socket_, endpoints,
            [this](boost::system::error_code ec, tcp::endpoint)
            {
                if(!ec)
                {
                    std::cout << "Async_connect Success!\n";
                    do_read_message();
                }
                else
                {
                    std::cout << "Async_connect error!\n";
                }
            });
    }

    void do_read_message()
    {
        std::cout << "read_message()" << std::endl;
        //auto self(shared_from_this());
        char *read_buffer = new char[128];
        boost::asio::async_read(socket_,
            boost::asio::buffer(read_buffer, 128),
            [this, read_buffer/*, self*/](boost::system::error_code ec, std::size_t size)
            {
                if(!ec)
                {
                    std::cout << "Async Read Success!\n";
                    read_msg_ = read_buffer;
                    if(read_msg_.length() != 0)
                    {
                        std::cout << "Message:" << read_msg_ << std::endl;
                        std::cout << "Length: " << read_msg_.length() << std::endl;
                        read_msg_ = "\0";
                    }
                    do_read_message();
                }
                else
                {
                    std::cout << "Async_read error!\n";
                    std::cerr << "Error:"  << ec.message() << std::endl;
                    socket_.close();
                }
            });
        std::cout << "do_read_message() is returned!\n";
    }

    void do_write(const std::string string)
    {
        write_msg_ = string;
        char *str = new char[sizeof(string.c_str())];
        memcpy(str,string.c_str(),sizeof(string.c_str()));
        boost::asio::async_write(socket_,
            boost::asio::buffer(str, 128),
            [this](boost::system::error_code ec, std::size_t)
            {
                if(!ec)
                {
                    std::cout << "Transport Success!" << std::endl;
                }
            });
    }


private:
    boost::asio::io_context& io_context_;
    tcp::socket socket_;
    echo_message read_msg_;
    echo_message write_msg_;
};

int main(int argc, char *argv[])
{
    try
    {
        if(argc != 3)
        {
            std::cerr << "Usage: client <host> <port>" << std::endl;
            return 1;
        }
        boost::asio::io_context io_context;

        tcp::resolver resolver(io_context);
        auto endpoints = resolver.resolve(argv[1], argv[2]);
        echo_client c(io_context, endpoints);

        std::thread t(
            [&io_context]()
            {
                io_context.run();
            });

        std::string line;
        while(std::cin >> line)
        {
            echo_message msg;
            msg = line;
            c.write(msg);
        }

        c.close();
        t.join();
    }
    catch(std::exception e)
    {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    return 0;
}
...