回答UDP数据包

Mar*_*lle 1 c++ qt qtnetwork qt5 qtcore

我有一个UDP服务器使用以下代码:

void initialize() 
{
    connect(&_udpSocket, SIGNAL(readyRead()), this, SLOT(onUdpDatagram()));

    _udpSocket.bind(QHostAddress::Any, 28283);
}

void onUdpDatagram()
{
    qDebug() << "udp packet received!";
    _udpSocket.write("Hello");
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,当收到UDP数据包时,我在日志中有以下错误:

QIODevice::write: device not open
Run Code Online (Sandbox Code Playgroud)

如何使UDP套接字可写?我尝试为连接到发件人地址和端口的答案创建另一个套接字,但发送将不再使用28283端口...

任何的想法?

有关信息:我在MacOS 10.9上使用Qt 5.2.1

lpa*_*app 8

巧合的是,这个警告是我在Qt上游引入的:

QIODevice :: write:设备未打开

它应该非常清楚,不像之前介绍的那样,即:你忘了用你的udp socket连接到主机.如果它甚至没有打开和/或连接,你不能指望它写和/或读.有关详细信息,请参阅文档

如果要使用标准QIODevice函数read(),readLine(),write()等,必须首先通过调用connectToHost()将套接字直接连接到对等体.

您必须在代码中的某处执行以下操作:

_udpSocket.connectToHost(myHostAddress, 28283, ReadWrite, AnyIPProtocol);
Run Code Online (Sandbox Code Playgroud)

最后两个参数可以跳过,因为它们是默认值.正如您可以从文档中读到的,此方法调用也将为您打开套接字,这对于完成QIODevice读写操作是必要的.

话虽这么说,你真的不应该忽视你的代码中的错误检查,因为它目前似乎是站立的.以这种方式找到问题将很困难.

此外,它是冰上蛋糕,但我鼓励你开始使用"新"信号槽语法,这不是那么新,但更现代和更方便:

void initialize() 
{    
    connect(&_udpSocket, &QUdpSocket::connected, [&_udpSocket]() {
        connect(&_udpSocket, &QUdpSocket::readyRead, [&_udpSocket]() {
            qDebug() << "udp packet received!";
            if (_udpSocket.write("Hello") != 6)
                qDebug() << "Failed to write:" << _udpSocket.errorString();
        });
    });
    connect(&_udpSocket, &QUdpSocket::error, [&_udpSocket]() {
        qDebug() << "Error occured:" << _udpSocket.errorString();
    });
    _udpSocket.connectToHost(myHostAddress, 28283, ReadWrite, AnyIPProtocol);
}
Run Code Online (Sandbox Code Playgroud)

  • `bind()`到`IPADDR_ANY`非常有意义,这意味着在所有本地接口上接收流量.将`connect()`称为有效对等体的地址是有意义的."0.0.0.0"永远不能是有效的对等体,甚至也不是有效的广播地址,那么该怎么做呢?将默认目标设置为随机本地接口?删除以前设置的默认目标?生成错误?POSIX没有说,真正的操作系统不同意.不,你不应该在`connectToHost()`中使用"0.0.0.0". (4认同)
  • 我不认为你可以使用`connectToHost`使用`QHostAddress :: Any`. (3认同)
  • 看起来它与`connectToHost("0.0.0.0",port,mode,proto)`相同,这将使它一直调用OS` :: connect`(在`qt_safe_connect`中),而不是任何意义.在大多数操作系统上都是错误的. (3认同)

Ben*_*igt 8

UDP不是基于连接的协议.您没有为每个对等体获得单独的套接字,而是在一个端口上有一个用于所有通信的套接字.

因此,需要额外的努力来回复传入的UDP数据包.您需要从收到的数据报中检索发件人地址,然后发回相同的地址.在套接字API中,这是通过使用recvfromsendto函数而不是recv(或read)和send(或write)来完成的 - 后者是为与TCP一起使用的连接套接字而设计的.

你没有显示你的_udpSocket变量的声明(实际上,类型),所以我假设你使用的是QUdpSocket.在这种情况下,看起来你会想要使用readDatagramwriteDatagram函数,它们recvfrom和对象sendto地址有一个额外的参数(实际上,它是一对,一个用于IP地址,一个用于端口).

以下是Qt文档中有关的内容:

使用此类的最常用方法是使用bind()绑定到地址和端口,然后调用writeDatagram()和readDatagram()来传输数据.如果要使用标准QIODevice函数read(),readLine(),write()等,必须首先通过调用connectToHost()将套接字直接连接到对等体.

  • 这个答案只说使用"B"而不是"A"; 换句话说,它甚至懒得定位问题的方向.此外,它甚至没有提供任何真正的代码来解决这个问题,只是重申每个人都可以阅读的文档. (2认同)