Silverlan
Silverlan

Reputation: 2901

"An existing connection was forcibly closed by the remote host" when listening for incoming data

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

Answers (1)

Tanner Sansbury
Tanner Sansbury

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

Related Questions