如何从 QUdpSocket 检测“端口不可达”条件?

问题描述

我正在尝试使用 QUdpSocket 将一些数据发送到明确定义的 host:port 目的地。当目标端口没有被监听时(例如客户端没有运行),ICMP 消息会显示“端口无法访问”。

我想在我的程序中检测这种情况并在它发生时采取行动。我在某处读到,如果我直接“连接”到主机,而不是仅仅对我的数据报进行“即发即弃”,那么应用程序应该会收到这些 ICMP 通知。但以下代码似乎没有出现任何错误

#include <QTimer>
#include <QString>
#include <QUdpSocket>
#include <QCoreApplication>

class DataSender : public QObject
{
public:
    DataSender(const QString& host,quint16 port);
    void send(const char* data,unsigned size);

private:
    void onSocketError(QUdpSocket::SocketError error);

private:
    QUdpSocket socket;
};

DataSender::DataSender(const QString& host,const quint16 port)
{
    connect(&socket,&QUdpSocket::connected,this,[]{qDebug() << "connected";});
    connect(&socket,&QUdpSocket::disconnected,[]{qDebug() << "disconnected";});
    connect(&socket,&QUdpSocket::hostFound,[]{qDebug() << "hostFound";});
    connect(&socket,qOverload<QUdpSocket::SocketError>(&QUdpSocket::error),&DataSender::onSocketError);
    socket.connectToHost(host,port,qiodevice::writeonly);
    qDebug() << "UDP server started";
}

void DataSender::send(const char*const data,const unsigned size)
{
    socket.write(data,size);
}

void DataSender::onSocketError(const QUdpSocket::SocketError)
{
    qDebug() << "UDP socket error:" << socket.errorString();
}

int main(int argc,char** argv)
{
    QCoreApplication app(argc,argv);

    DataSender sender("127.0.0.1",33333);

    QTimer timer;
    QObject::connect(&timer,&QTimer::timeout,[&sender]{ sender.send("Test",4); });
    timer.start(1000);

    return app.exec();
}

输出中我只得到

hostFound
connected
UDP server started

同时,在运行此测试时,我确实在 Wireshark 中看到了“无法访问端口”的 ICMP 消息。我如何才能真正接收和处理它们?

我发现在 Linux 套接字 API 中,write(2) 系统调用在这种情况下返回 -1 和 errno=ECONNREFUSED。但是对于 QUdpSocket,我想获得一个跨平台的解决方案。我还发现 syscall-set errno 似乎在 QUdpSocket::write() 返回后被保留,所以我可以使用它,但这是特定于 Linux 的,而我的目标平台列表还包括 Windows。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)