Reputation: 3619
Combining the information from boost docs and manual for connect function I take it that the asio::udp::socket::connect function serves to set the address to which datagrams are sent by default, and the only address from which datagrams are received.
This works nicely but the manual also states that I should be able to dissolve the association (disconnect), which is what I'm having problem doing. I.e. I would like the socket to start receiving packets from any address again.
Further in the manual is written:
Connectionless sockets may dissolve the association by connecting to an
address with the sa_family member of sockaddr set to AF_UNSPEC.
I have tried this code:
asio::udp::endpoint unspecified_endpoint;
assert(unspecified_endpoint.address().is_unspecified()); // OK
socket.connect(unspecified_endpoint);
But that did not help.
EDIT: Created a test case by taking the client and server examples from boost::asio page. In client code, I've changed the outgoing port number from random to 5192:
udp::socket s(io_service, udp::endpoint(udp::v4(), 5192));
And I changed the function server in the server code:
void server(boost::asio::io_service& io_service, short port)
{
udp::socket sock(io_service, udp::endpoint(udp::v4(), port));
#define CASE 3
#if CASE == 1
sock.connect(udp::endpoint());
#elif CASE == 2
sock.connect(udp::endpoint(ip::address::from_string("127.0.0.1"), 5193));
sock.connect(udp::endpoint());
#elif CASE == 3
sock.connect(udp::endpoint(ip::address::from_string("192.168.1.3"), 5192));
sock.connect(udp::endpoint());
#endif
for (;;)
{
char data[max_length];
udp::endpoint sender_endpoint;
size_t length = sock.receive_from(
boost::asio::buffer(data, max_length), sender_endpoint);
sock.send_to(boost::asio::buffer(data, length), sender_endpoint);
}
}
Cases 1 and 2 seem to work, but in case 3 the client wont receive a reply. The full source can be found here.
Upvotes: 2
Views: 1916
Reputation: 121
To keep access to library functions, use the fact that udp::endpoint
is just a wrapper around sockaddr
. Construct sockaddr
with a specific value and cast it to the required type.
sock.connect(reinterpret_cast<const udp::endpoint &>(static_cast<const sockaddr &>(sockaddr{ AF_UNSPEC })));
Upvotes: 0
Reputation: 7356
As mentioned in the comments, the call to sock.connect(udp::endpoint());
translates to connect(6, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
which isn't the same as a connect
with AF_UNSPEC
and doesn't completely disconnect the UDP socket (it appears to only reset the peer port number).
I don't think there is a way to achieve what you want purely with boost asio, but you could just use a native POSIX call to disconnect the socket, something like
struct sockaddr unspec_addr = { AF_UNSPEC };
::connect(sock.native_handle(), &unspec_addr, sizeof(unspec_addr));
Debugging notes: run the program with strace
and then use netstat -nu
to list the UDP sockets.
Upvotes: 2