Reputation: 113
I am using boost beast WebSocket, and trying to bind it locally to a particular interface via bind, the bind happens(reflected in log), but in async connect handler I see some other endpoint (default interface), instead of the local one. Why can this be happening?
boost::optional<boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>> stream_;
boost::asio::socket_base::reuse_address option(true);
stream_->next_layer().next_layer().open(boost::asio::ip::tcp::v4());
stream_->next_layer().next_layer().set_option(option);
stream_->next_layer().next_layer().bind(boost::asio::ip::tcp::endpoint(
boost::asio::ip::address::from_string(interface_), 0));
auto local_endpoint = stream_->next_layer().next_layer().local_endpoint();
LOG("WS session:", session_id_, " from:", local_endpoint.address().to_string(),
local_endpoint.port(), interface_, stream_->next_layer().next_layer().native_handle());
here the logging is correct.
boost::asio::async_connect( stream_->next_layer().next_layer(), res.begin(), res.end(), boost::bind(&WebSocketSession::on_connect, this, boost::asio::placeholders::error) );
post this, in the handler (on_connect) the bind seems to be resetted to some other interface(default interface of the machine).
void on_connect(const boost::system::error_code& error) { auto tp = language::datetime::clock_realtime(); auto local_endpoint = stream_->next_layer().next_layer().local_endpoint(); LOG("WS session: on_connect from:", local_endpoint.address().to_string(), local_endpoint.port(),interface_,stream_->next_layer().next_layer().is_open(), stream_->next_layer().next_layer().native_handle());
In both cases is_open is logged as true and the native file descriptor is also same in both
Upvotes: 0
Views: 393
Reputation: 1
I basically have a same problem. I noticed that there are a lots of answers said asio::connect() static method will close the opened socket and re-open it. So the socket binded IP was closed and the new socket is set to default.
I guess async_connect() static method is similar. So I check the connect.hpp file:
template <typename Protocol, typename SocketService, typename Iterator,
typename ConnectCondition, typename ComposedConnectHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler,
void (boost::system::error_code, Iterator))
async_connect(basic_socket<Protocol, SocketService>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ComposedConnectHandler.
BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK(
ComposedConnectHandler, handler, Iterator) type_check;
detail::async_result_init<ComposedConnectHandler,
void (boost::system::error_code, Iterator)> init(
BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler));
detail::connect_op<Protocol, SocketService, Iterator,
ConnectCondition, BOOST_ASIO_HANDLER_TYPE(
ComposedConnectHandler, void (boost::system::error_code, Iterator))>(s,
begin, end, connect_condition, init.handler)(
boost::system::error_code(), 1);
return init.result.get();
}
Actually it calls detail::connect_op:
void operator()(boost::system::error_code ec, int start = 0)
{
switch (start_ = start)
{
case 1:
for (;;)
{
this->check_condition(ec, iter_, end_);
if (iter_ != end_)
{
socket_.close(ec); // <---- HERE!
socket_.async_connect(*iter_,
BOOST_ASIO_MOVE_CAST(connect_op)(*this));
return;
}
if (start)
{
ec = boost::asio::error::not_found;
socket_.get_io_service().post(detail::bind_handler(*this, ec));
return;
}
In summary, please use socket.async_connect() instead of asio::async_connect().
Upvotes: 0