Thread: boost::asio::dynamic_buffer doesn't work?

  1. #1
    Registered User Chris87's Avatar
    Join Date
    Dec 2007
    Posts
    139

    boost::asio::dynamic_buffer doesn't work?

    To learn about utilising coroutines in networking, I've been studing its use in Boost.Asio's chat server example. (doc/html/boost_asio/example/cpp17/coroutines_ts/chat_server.cpp - 1.76.0 ). However, the examples do not provide a client counterpart example. Now, I found that this is an adaptation of an earlier C++11 example, which does have a client example.

    However, the older example uses the method of a header and body, whereas the newer example uses a read-until-newline method. I've tried rewriting the older client example to reflect that. Though both compile, I opened Wireshark to check what's being sent and received. The client is able to send the message, the server acknowledges that it receives the message, but it doesn't relay it.

    Using breakpoints, I found that the server executes the async_read_until co_await, but nothing after that is ever called.

    Along with the aforementioned linked example, here's the rewritten client example intended to work with it. I've been building this in VS2019 using /std:c++latest so I could leverage coroutines.

    Code:
    #include <iostream>
    #include <boost/asio.hpp>
    #include <exception>
    #include <system_error>
    #include <deque>
    #include <cstdint>
    #include <string>
    #include <cstring>
    #include <utility>
    #include <thread>
    #include <sstream>
    #include <memory>
    
    
    class client : public std::enable_shared_from_this<client>
    {
    public:
    	client(boost::asio::io_context &ctx,
    		const boost::asio::ip::tcp::resolver::results_type &eps):
    		m_ctx(ctx), m_sock(ctx)
    	{
    		connect(eps);
    	}
    
    	void connect(const boost::asio::ip::tcp::resolver::results_type &eps)
    	{
    		boost::asio::async_connect(m_sock, eps,
    			[this](std::error_code ec, boost::asio::ip::tcp::endpoint)
    			{
    				if (ec) std::cerr << "Connect! ... aaaaaaand missed!" << std::endl;
    				else
    					co_spawn(m_sock.get_executor(), [self = shared_from_this()]
    					{
    						return self->read();
    					}, boost::asio::detached);
    			});
    	}
    
    	void write(std::string &msg)
    	{
    		bool hasWork = !msgs.empty();
    		msgs.push_back(msg);
    
    		boost::asio::post(m_ctx, [this, hasWork]
    		{
    			if (!hasWork) do_write();
    		});
    	}
    
    	void close()
    	{
    		boost::asio::post(m_ctx, [this]()
    		{
    			m_sock.close();
    		});
    	}
    private:
    	boost::asio::io_context &m_ctx;
    	boost::asio::ip::tcp::socket m_sock;
    	std::deque<std::string> msgs;
    
    	boost::asio::awaitable<void> read()
    	{
    		try
    		{
    			for (boost::asio::streambuf read_tmp;;)
    			{
    				co_await boost::asio::async_read_until(m_sock, read_tmp, 0, boost::asio::use_awaitable);
    
    				std::cout << &read_tmp << std::endl;
    			}
    		}
    		catch (std::exception &e)
    		{
    			std::cerr << e.what() << std::endl;
    			m_sock.close();
    		}
    	}
    
    	void do_write()
    	{
    		boost::asio::async_write(m_sock, boost::asio::buffer(msgs.front(), std::strlen(msgs.front().data())),
    			[this](std::error_code ec, std::size_t)
    			{
    				if (ec)
    				{
    					std::cerr << "How can you write this? There's no pictures!" << std::endl;
    					m_sock.close();
    				}
    				else
    				{
    					msgs.pop_front();
    					if (!msgs.empty()) do_write();
    				}
    			});
    	}
    };
    
    int main(int argc, char **argv)
    {
    	try
    	{
    		if (argc != 3)
    		{
    			std::cerr << "Usage: " << argv[0] << " <host> <port>" << std::endl;
    			return 1;
    		}
    
    		boost::asio::io_context ctx;
    		boost::asio::ip::tcp::resolver res(ctx);
    		auto eps = res.resolve(argv[1], argv[2]);
    		std::shared_ptr<client> c = std::make_shared<client>(ctx, eps);
    
    		std::thread thr([&ctx]()
    		{
    			ctx.run();
    		});
    
    		std::string input(1024, 0);
    
    		while (std::cin.getline(input.data(), 1024))
    		{
    			input += '\n';
    			c->write(input);
    		}
    
    		c->close();
    		if (thr.joinable()) thr.join();
    	}
    	catch (std::exception &e)
    	{
    		std::cerr << "Ya ........ed up: " << e.what() << std::endl;
    	}
    }
    Last edited by Chris87; 07-28-2021 at 12:16 PM. Reason: wrong url

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. http server using boost asio
    By EverydayDiesel in forum C++ Programming
    Replies: 6
    Last Post: 02-05-2018, 05:00 PM
  2. Using boost::asio (2)
    By sean_cantab in forum C++ Programming
    Replies: 0
    Last Post: 09-09-2017, 08:36 PM
  3. Using boost::asio
    By sean_cantab in forum C++ Programming
    Replies: 12
    Last Post: 08-04-2017, 12:26 AM
  4. Boost Asio and asynchronous I/O
    By Elysia in forum C++ Programming
    Replies: 9
    Last Post: 06-19-2011, 07:51 PM
  5. Boost ASIO
    By PetrolMan in forum C++ Programming
    Replies: 0
    Last Post: 04-10-2009, 03:24 PM

Tags for this Thread