“侦听传入数据时,”远程主机强制关闭现有连接“

时间:2015-12-11 13:14:17

标签: c++ windows networking listener boost-asio

在使用boost asio时,我偶然发现了一些奇怪的行为,我不太明白。我写了一个最小的测试程序来复制问题:

#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;
}

如果'send_to'调用的目标端点存在且正在侦听,则此程序运行正常。数据正确发送,然后等待传入数据。

但是,如果目标端点不存在,则行为非常意外。 'send_to'调用仍然调度数据而没有任何错误,但是当尝试接收数据时,'receive'调用立即返回,并且我得到“现有连接被远程主机强行关闭”错误。这对我没有任何意义。首先,没有远程主机,因为没有数据被发送到侦听器端口。其次,根据我的理解,该程序中的接收和发送部分应该是完全独立的,并且不应该相互影响。我错了这个假设吗?

//编辑:

我刚刚意识到这个消息没有任何意义的另一个原因。我正在使用无连接的UDP协议,那么“连接​​”是什么关闭的?

1 个答案:

答案 0 :(得分:1)

虽然UDP通常被称为无连接协议,但上下文意味着无状态协议。因此,UDP被允许返回一些与连接相关的错误消息:

  

socketip记录的所有错误都可能由UDP套接字上的发送或接收返回。

     

ECONNREFUSED
  没有接收器与目标地址相关联。这可能是由通过套接字发送的之前的数据包引起的。

Winsock recvfrom()函数记录了对于UDP,如果先前的发送操作导致ICMP Port Unreachable消息,则该函数将错误WSAECONNRESET

  

WSAECONNRESET
  [...]在UDP数据报套接字上,此错误表示先前的发送操作导致ICMP端口无法访问消息。