Reputation: 2901
When working with boost asio, I've stumbled upon some weird behavior, which I don't quite understand. I wrote a minimal test-program to replicate the problem:
#include <boost/asio.hpp>
#include <iostream>
using boost::asio::ip::udp;
int main(int argc,char *argv[])
{
boost::asio::io_service ioService;
udp::resolver resolver(ioService);
udp::resolver::query queryListen("127.0.0.1","50001");
auto epListen = *resolver.resolve(queryListen);
udp::socket socket(ioService,epListen);
udp::resolver::query querySend("127.0.0.1","55006");
auto epSend = *resolver.resolve(querySend);
boost::system::error_code err;
std::array<char,12> buffer = {'1','2','3','4','5','6','7','8','9','10','11','12'};
socket.send_to(
boost::asio::buffer(&buffer[0],buffer.size()),
epSend,0,err
);
if(!err)
{
std::cout<<"Sent successfully!"<<std::endl;
auto numBytes = socket.receive(
boost::asio::buffer(&buffer[0],buffer.size()),0,
err
);
if(!err)
std::cout<<"Received "<<numBytes<<" bytes successfully!"<<std::endl;
else
std::cout<<"Unable to receive: "<<err.message()<<std::endl; // This is where I'm getting the message "An existing connection was forcibly closed by the remote host"
}
else
std::cout<<"Unable to send: "<<err.message()<<std::endl;
for(;;);
return 0;
}
If the destination endpoint for the 'send_to'-call exists and is listening, this program runs just fine. The data is sent correctly, and it then waits for incoming data.
However, if the destination endpoint doesn't exist, the behavior is rather unexpected. The 'send_to'-call still dispatches the data without any errors, but when trying to receive data, the 'receive'-call immediately returns, and I'm getting a "An existing connection was forcibly closed by the remote host" error. This doesn't make any sense to me. First of all, there is no remote host, since there is no data being sent to the listener port. Secondly, from what I understand, the receiving- and the sending-part in this program should be completely independent, and shouldn't affect each other at all. Am I wrong in that assumption?
// Edit:
I've just realized that there's another reason why that message doesn't make any sense. I'm using the UDP procotol, which is connectionless, so what 'connection' was closed?
Upvotes: 1
Views: 1800
Reputation: 51871
While UDP is often referred to as a connectionless protocol, the context implies a stateless protocol. As such, UDP is permitted to return some connect-related error messages:
All errors documented for socket or ip may be returned by a send or receive on a UDP socket.
ECONNREFUSED
No receiver was associated with the destination address. This might be caused by a previous packet sent over the socket.
The Winsock recvfrom()
function documents that for UDP, the function will error with WSAECONNRESET
if a prior send operation resulted in an ICMP Port Unreachable message:
WSAECONNRESET
[...] On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message.
Upvotes: 1