No passado, escrevi um servidor tcp simples usando a biblioteca boost e o código abaixo funcionando corretamente.
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class session
: public std::enable_shared_from_this<session>
{
public:
session(tcp::socket socket)
: socket_(std::move(socket))
{
}
void start()
{
do_read();
}
private:
void do_read()
{
auto self(shared_from_this());
socket_.async_read_some(boost::asio::buffer(data_, max_length),
[this, self](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
do_write(length);
}
});
}
void do_write(std::size_t length)
{
auto self(shared_from_this());
boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
do_read();
}
});
}
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
class server
{
public:
server(boost::asio::io_context& io_context, short port)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
{
do_accept();
}
private:
void do_accept()
{
acceptor_.async_accept(
[this](boost::system::error_code ec, tcp::socket socket)
{
if (!ec)
{
std::make_shared<session>(std::move(socket))->start();
}
do_accept();
});
}
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: async_tcp_echo_server <port>\n";
return 1;
}
boost::asio::io_context io_context;
server s(io_context, std::atoi(argv[1]));
io_context.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
Agora eu quero usar o arquivo de soquete chamado "mysocket" e usá-lo em vez de ip/port. E eu mudei apenas abaixo das linhas. Também espero que o arquivo "mysocket" seja criado automaticamente a partir da linha a seguir. Então eu não o criei manualmente.
server(boost::asio::io_context& io_context, short port)
: acceptor_(io_context, boost::asio::local::stream_protocol::endpoint("mysocket"))
{
do_accept();
}
boost::asio::local::stream_protocol::acceptor acceptor_;
Mas eu não compilo e dá o erro abaixo. Como posso consertar isso?
main.cpp: In member function ‘void server::do_accept()’:
main.cpp:67:27: error: no matching function for call to ‘boost::asio::basic_socket_acceptor<boost::asio::local::stream_protocol>::async_accept(server::do_accept()::<lambda(boost::system::error_code, boost::asio::ip::tcp::socket)>)’
67 | acceptor_.async_accept(
68 | [this](boost::system::error_code ec, tcp::socket socket)
69 | {
| ~
70 | if (!ec)
71 | {
| ~
72 | std::make_shared<session>(std::move(socket))->start();
73 | }
| ~
75 | do_accept();
76 | });
| ~~
In file included from /usr/local/include/boost/asio.hpp:43,
from main.cpp:5:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:1398:3: note: candidate: ‘template<class Protocol1, class Executor1, class AcceptToken> requires completion_token_for<AcceptToken, void()> auto boost::asio::basic_socket_acceptor<Protocol, Executor>::async_accept(boost::asio::basic_socket<Protocol1, Executor1>&, AcceptToken&&, typename boost::asio::constraint<std::is_convertible<Protocol, Protocol1>::value>::type) [with Protocol1 = Protocol1; Executor1 = Executor1; AcceptToken = AcceptToken; Protocol = boost::asio::local::stream_protocol; Executor = boost::asio::any_io_executor]’
1398 | async_accept(basic_socket<Protocol1, Executor1>& peer,
| ^~~~~~~~~~~~
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:1398:3: note: template argument deduction/substitution failed:
main.cpp:67:27: note: ‘server::do_accept()::<lambda(boost::system::error_code, boost::asio::ip::tcp::socket)>’ is not derived from ‘boost::asio::basic_socket<Protocol, Executor>’
67 | acceptor_.async_accept(
| ~~~~~~~~~~~~~~~~~~~~~~^
68 | [this](boost::system::error_code ec, tcp::socket socket)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 | {
| ~
70 | if (!ec)
| ~~~~~~~~
71 | {
| ~
72 | std::make_shared<session>(std::move(socket))->start();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
73 | }
| ~
74 |
|
75 | do_accept();
| ~~~~~~~~~~~~
76 | });
| ~~
In file included from /usr/local/include/boost/asio.hpp:43,
from main.cpp:5:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:1531:3: note: candidate: ‘template<class Executor1, class AcceptToken> requires completion_token_for<AcceptToken, void()> auto boost::asio::basic_socket_acceptor<Protocol, Executor>::async_accept(boost::asio::basic_socket<Protocol, Executor1>&, boost::asio::basic_socket_acceptor<Protocol, Executor>::endpoint_type&, AcceptToken&&) [with Executor1 = Executor1; AcceptToken = AcceptToken; Protocol = boost::asio::local::stream_protocol; Executor = boost::asio::any_io_executor]’
1531 | async_accept(basic_socket<protocol_type, Executor1>& peer,
| ^~~~~~~~~~~~
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:1531:3: note: template argument deduction/substitution failed:
main.cpp:67:27: note: ‘server::do_accept()::<lambda(boost::system::error_code, boost::asio::ip::tcp::socket)>’ is not derived from ‘boost::asio::basic_socket<boost::asio::local::stream_protocol, Executor1>’
67 | acceptor_.async_accept(
| ~~~~~~~~~~~~~~~~~~~~~~^
68 | [this](boost::system::error_code ec, tcp::socket socket)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 | {
| ~
70 | if (!ec)
| ~~~~~~~~
71 | {
| ~
72 | std::make_shared<session>(std::move(socket))->start();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
73 | }
| ~
74 |
|
75 | do_accept();
| ~~~~~~~~~~~~
76 | });
| ~~
In file included from /usr/local/include/boost/asio.hpp:43,
from main.cpp:5:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:1679:3: note: candidate: ‘template<class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<Protocol, Executor>::async_accept(MoveAcceptToken&&) [with MoveAcceptToken = MoveAcceptToken; Protocol = boost::asio::local::stream_protocol; Executor = boost::asio::any_io_executor]’
1679 | async_accept(
| ^~~~~~~~~~~~
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:1679:3: note: template argument deduction/substitution failed:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:1679:3: note: constraints not satisfied
In file included from /usr/local/include/boost/asio/detail/handler_type_requirements.hpp:53,
from /usr/local/include/boost/asio/impl/execution_context.hpp:18,
from /usr/local/include/boost/asio/execution_context.hpp:409,
from /usr/local/include/boost/asio/detail/scheduler.hpp:21,
from /usr/local/include/boost/asio/system_context.hpp:19,
from /usr/local/include/boost/asio/impl/system_executor.hpp:21,
from /usr/local/include/boost/asio/system_executor.hpp:671,
from /usr/local/include/boost/asio/associated_executor.hpp:24,
from /usr/local/include/boost/asio/any_completion_handler.hpp:28,
from /usr/local/include/boost/asio.hpp:21,
from main.cpp:5:
/usr/local/include/boost/asio/async_result.hpp: In substitution of ‘template<class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<boost::asio::local::stream_protocol>::async_accept<MoveAcceptToken>(MoveAcceptToken&&) [with MoveAcceptToken = boost::asio::local::stream_protocol]’:
main.cpp:67:27: required from here
/usr/local/include/boost/asio/async_result.hpp:1209:20: required for the satisfaction of ‘completion_token_for<MoveAcceptToken, void(boost::system::error_code, typename Protocol::socket::rebind_executor<Executor>::other)>’ [with MoveAcceptToken = server::do_accept::._anon_255; Executor = boost::asio::any_io_executor; Protocol = boost::asio::local::stream_protocol]
/usr/local/include/boost/asio/async_result.hpp:1212:3: in requirements with ‘T&& t’ [with Signatures = {void()}; T = server::do_accept::._anon_255]
/usr/local/include/boost/asio/async_result.hpp:1214:37: note: the required expression ‘async_initiate<T, Signatures ...>(boost::asio::detail::initiation_archetype<Signatures ...>{}, t)’ is invalid
1214 | async_initiate<T, Signatures...>(
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
1215 | detail::initiation_archetype<Signatures...>{}, t);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: set ‘-fconcepts-diagnostics-depth=’ to at least 2 for more detail
In file included from /usr/local/include/boost/asio.hpp:43,
from main.cpp:5:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:1936:3: note: candidate: ‘template<class Executor1, class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<Protocol, Executor>::async_accept(const Executor1&, MoveAcceptToken&&, typename boost::asio::constraint<(boost::asio::is_executor<Executor1>::value || boost::asio::execution::is_executor<T>::value)>::type) [with Executor1 = Executor1; MoveAcceptToken = MoveAcceptToken; Protocol = boost::asio::local::stream_protocol; Executor = boost::asio::any_io_executor]’
1936 | async_accept(const Executor1& ex,
| ^~~~~~~~~~~~
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:1936:3: note: template argument deduction/substitution failed:
main.cpp: In substitution of ‘template<class Executor1, class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<boost::asio::local::stream_protocol>::async_accept<Executor1, MoveAcceptToken>(const Executor1&, MoveAcceptToken&&, typename boost::asio::constraint<(boost::asio::is_executor<Executor>::value || boost::asio::execution::is_executor<T>::value)>::type) [with Executor1 = boost::asio::local::stream_protocol; MoveAcceptToken = boost::asio::any_io_executor]’:
main.cpp:67:27: required from here
/usr/local/include/boost/asio/async_result.hpp:1209:20: required for the satisfaction of ‘completion_token_for<MoveAcceptToken, void(boost::system::error_code, typename Protocol::socket::rebind_executor<typename boost::asio::constraint<(boost::asio::is_executor<Executor1>::value || boost::asio::execution::is_executor<T>::value), Executor1>::type>::other)>’ [with MoveAcceptToken = void; Executor1 = server::do_accept::._anon_255; Protocol = boost::asio::local::stream_protocol]
main.cpp:67:27: error: no type named ‘type’ in ‘struct boost::asio::constraint<false, server::do_accept()::<lambda(boost::system::error_code, boost::asio::ip::tcp::socket)> >’
67 | acceptor_.async_accept(
| ~~~~~~~~~~~~~~~~~~~~~~^
68 | [this](boost::system::error_code ec, tcp::socket socket)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 | {
| ~
70 | if (!ec)
| ~~~~~~~~
71 | {
| ~
72 | std::make_shared<session>(std::move(socket))->start();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
73 | }
| ~
74 |
|
75 | do_accept();
| ~~~~~~~~~~~~
76 | });
| ~~
In file included from /usr/local/include/boost/asio.hpp:43,
from main.cpp:5:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2035:3: note: candidate: ‘template<class ExecutionContext, class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<Protocol, Executor>::async_accept(ExecutionContext&, MoveAcceptToken&&, typename boost::asio::constraint<std::is_convertible<ExecutionContext&, boost::asio::execution_context&>::value>::type) [with ExecutionContext = ExecutionContext; MoveAcceptToken = MoveAcceptToken; Protocol = boost::asio::local::stream_protocol; Executor = boost::asio::any_io_executor]’
2035 | async_accept(ExecutionContext& context,
| ^~~~~~~~~~~~
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2035:3: note: template argument deduction/substitution failed:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2035:3: note: constraints not satisfied
main.cpp: In substitution of ‘template<class ExecutionContext, class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<boost::asio::local::stream_protocol>::async_accept<ExecutionContext, MoveAcceptToken>(ExecutionContext&, MoveAcceptToken&&, typename boost::asio::constraint<std::is_convertible<ExecutionContext&, boost::asio::execution_context&>::value>::type) [with ExecutionContext = boost::asio::local::stream_protocol; MoveAcceptToken = boost::asio::any_io_executor]’:
main.cpp:67:27: required from here
/usr/local/include/boost/asio/async_result.hpp:1209:20: required for the satisfaction of ‘completion_token_for<MoveAcceptToken, void(boost::system::error_code, typename Protocol::socket::rebind_executor<typename ExecutionContext::executor_type>::other)>’ [with MoveAcceptToken = void; ExecutionContext = server::do_accept::._anon_255; Protocol = boost::asio::local::stream_protocol]
main.cpp:67:27: error: no type named ‘executor_type’ in ‘struct server::do_accept()::<lambda(class boost::system::error_code, boost::asio::ip::tcp::socket)>’
67 | acceptor_.async_accept(
| ~~~~~~~~~~~~~~~~~~~~~~^
68 | [this](boost::system::error_code ec, tcp::socket socket)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 | {
| ~
70 | if (!ec)
| ~~~~~~~~
71 | {
| ~
72 | std::make_shared<session>(std::move(socket))->start();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
73 | }
| ~
74 |
|
75 | do_accept();
| ~~~~~~~~~~~~
76 | });
| ~~
In file included from /usr/local/include/boost/asio.hpp:43,
from main.cpp:5:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2211:3: note: candidate: ‘template<class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<Protocol, Executor>::async_accept(boost::asio::basic_socket_acceptor<Protocol, Executor>::endpoint_type&, MoveAcceptToken&&) [with MoveAcceptToken = MoveAcceptToken; Protocol = boost::asio::local::stream_protocol; Executor = boost::asio::any_io_executor]’
2211 | async_accept(endpoint_type& peer_endpoint,
| ^~~~~~~~~~~~
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2211:3: note: template argument deduction/substitution failed:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2211:3: note: constraints not satisfied
In file included from /usr/local/include/boost/asio/detail/handler_type_requirements.hpp:53,
from /usr/local/include/boost/asio/impl/execution_context.hpp:18,
from /usr/local/include/boost/asio/execution_context.hpp:409,
from /usr/local/include/boost/asio/detail/scheduler.hpp:21,
from /usr/local/include/boost/asio/system_context.hpp:19,
from /usr/local/include/boost/asio/impl/system_executor.hpp:21,
from /usr/local/include/boost/asio/system_executor.hpp:671,
from /usr/local/include/boost/asio/associated_executor.hpp:24,
from /usr/local/include/boost/asio/any_completion_handler.hpp:28,
from /usr/local/include/boost/asio.hpp:21,
from main.cpp:5:
/usr/local/include/boost/asio/async_result.hpp: In substitution of ‘template<class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<boost::asio::local::stream_protocol>::async_accept<MoveAcceptToken>(boost::asio::basic_socket_acceptor<boost::asio::local::stream_protocol>::endpoint_type&, MoveAcceptToken&&) [with MoveAcceptToken = boost::asio::local::stream_protocol]’:
main.cpp:67:27: required from here
/usr/local/include/boost/asio/async_result.hpp:1209:20: required for the satisfaction of ‘completion_token_for<MoveAcceptToken, void(boost::system::error_code, typename Protocol::socket::rebind_executor<Executor>::other)>’ [with MoveAcceptToken = void; Executor = boost::asio::any_io_executor; Protocol = boost::asio::local::stream_protocol]
/usr/local/include/boost/asio/async_result.hpp:1212:3: in requirements with ‘T&& t’ [with Signatures = {void()}; T = void]
/usr/local/include/boost/asio/async_result.hpp:1212:3: error: forming reference to void
1212 | requires(T&& t)
| ^~~~~~~~~~~~~~~
1213 | {
| ~
1214 | async_initiate<T, Signatures...>(
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1215 | detail::initiation_archetype<Signatures...>{}, t);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1216 | };
| ~
In file included from /usr/local/include/boost/asio.hpp:43,
from main.cpp:5:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2500:3: note: candidate: ‘template<class Executor1, class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<Protocol, Executor>::async_accept(const Executor1&, boost::asio::basic_socket_acceptor<Protocol, Executor>::endpoint_type&, MoveAcceptToken&&, typename boost::asio::constraint<(boost::asio::is_executor<Executor1>::value || boost::asio::execution::is_executor<T>::value)>::type) [with Executor1 = Executor1; MoveAcceptToken = MoveAcceptToken; Protocol = boost::asio::local::stream_protocol; Executor = boost::asio::any_io_executor]’
2500 | async_accept(const Executor1& ex, endpoint_type& peer_endpoint,
| ^~~~~~~~~~~~
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2500:3: note: template argument deduction/substitution failed:
main.cpp:67:27: note: candidate expects 4 arguments, 1 provided
67 | acceptor_.async_accept(
| ~~~~~~~~~~~~~~~~~~~~~~^
68 | [this](boost::system::error_code ec, tcp::socket socket)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 | {
| ~
70 | if (!ec)
| ~~~~~~~~
71 | {
| ~
72 | std::make_shared<session>(std::move(socket))->start();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
73 | }
| ~
74 |
75 | do_accept();
76 | });
In file included from /usr/local/include/boost/asio.hpp:43,
from main.cpp:5:
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2603:3: note: candidate: ‘template<class ExecutionContext, class MoveAcceptToken> requires completion_token_for<MoveAcceptToken, void()> auto boost::asio::basic_socket_acceptor<Protocol, Executor>::async_accept(ExecutionContext&, boost::asio::basic_socket_acceptor<Protocol, Executor>::endpoint_type&, MoveAcceptToken&&, typename boost::asio::constraint<std::is_convertible<ExecutionContext&, boost::asio::execution_context&>::value>::type) [with ExecutionContext = ExecutionContext; MoveAcceptToken = MoveAcceptToken; Protocol = boost::asio::local::stream_protocol; Executor = boost::asio::any_io_executor]’
2603 | async_accept(ExecutionContext& context,
/usr/local/include/boost/asio/basic_socket_acceptor.hpp:2603:3: note: template argument deduction/substitution failed:
main.cpp:67:27: note: candidate expects 4 arguments, 1 provided
67 | acceptor_.async_accept(
| ~~~~~~~~~~~~~~~~~~~~~~^
68 | [this](boost::system::error_code ec, tcp::socket socket)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 | {
| ~
70 | if (!ec)
| ~~~~~~~~
71 | {
| ~
72 | std::make_shared<session>(std::move(socket))->start();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
75 | do_accept();
76 | });
Versão do meu boost:
#include <boost/version.hpp>
#include <iostream>
int main() {
std::cout << "Using Boost "
<< BOOST_VERSION / 100000 << "." // major version
<< BOOST_VERSION / 100 % 1000 << "." // minor version
<< BOOST_VERSION % 100 // patch level
<< std::endl;
return 0;
}
Using Boost 1.82.0
Você precisa alterar o tipo de soquete na classe de sessão. Abstraindo um pouco melhor:
Ao vivo no Coliru
Você pode facilmente mudar tudo para TCP alternando as 3 linhas comentadas