没有绑定,QUdpSocket无法正常工作

时间:2017-09-13 13:11:48

标签: qt network-programming udp qt5 qudpsocket

我必须通过UDP与某些设备通信。问题是如果没有QUdpSocket的特殊情况,bind()根本不起作用。我使用connectToHost()方法for access to read()/write() functions

使用代码时,UDP交换完全不起作用:

m_udp.connectToHost(QHostAddress("192.168.100.15"), 4001);    
m_udp.waitForConnected();

我没有收到任何字节。 Wireshark中的消息:

QUdpSocket error in Wireshark

以下代码也不起作用:

m_udp.bind(QHostAddress("192.168.100.15"), 4001);
m_udp.connectToHost(QHostAddress("192.168.100.15"), 4001);    
m_udp.waitForConnected();

只有这段代码有效:

m_udp.bind(4001);
m_udp.connectToHost(QHostAddress("192.168.100.15"), 4001);    
m_udp.waitForConnected();

但是代码只适用于Qt 5.6.2,而不适用于Qt 5.4.2。 以下是我尝试接收的方式:

dev->waitForReadyRead(500);
QByteArray ba = dev->readAll();

为什么这种行为如此奇怪?怎么能理解这个?

2 个答案:

答案 0 :(得分:2)

您还没有显示另一方的代码,但显然来自所示的wireshark图像,远程对等方希望您的套接字绑定到端口4001.

第一个代码片段尝试连接到(RemoteAddress,4001)而没有指定本地端口(因此内核分配了一个任意端口号(根据wireshark的64875),但如上所述,另一方是期待发送回端口4001.因此您无法在端口64875上接收它。

在UDP中,没有实际连接这样的东西。当您使用connectToHost时,您实际上只指定了远程端的IP地址和端口号。应用程序负责确保远程端发送回正确的端口。这可以通过以下方式完成:(a)始终发送到特定端口(这显然是在这里完成),或者(b)另一方可以查看实际接收数据报的地址/端口并发回给它;换句话说,远程端可以确定它收到的数据报是从端口64875发送的,并将其回复目标定位到该端口。

在第二次尝试中,您尝试将本地端点绑定到另一台机器上的地址,这根本没有任何意义。 (如果您将绑定更改为m_udp.bind(QHostAddress("192.168.100.3"), 4001); - 本地计算机的IP地址,我猜这个代码段会起作用。)

只有第三个代码段可以正常工作,因为在这里您没有指定IP地址就绑定到本地端口4001,然后还发送到远程计算机上的端口4001。如果仅指定bind中的端口号,则IP地址将保留为"通配符"因此,您应该在您的任何机器的IP地址上获取发送到该端口号的数据包。

(不知道为什么你会在早期版本的Qt中看到不同的行为。)

答案 1 :(得分:1)

在写入或读取之前检查绑定后的套接字状态。

请参阅此代码:

QHostAddress serverIP("172.168.1.100");
if(socket->bind(serverIP,port,QUdpSocket::ShareAddress)) //even if local Host dont have static IP( on subnet expected 172.168.x.x),still it becomes true and enters if.
    {
    if( (socket->state() == QAbstractSocket::BoundState) && (((socket->localAddress()).protocol()) == QAbstractSocket::IPv4Protocol) ) //ignore protocol validation if not required.
        {

         }
 else
        {
            qDebug()<<"Socket not in bound state. address is: "<<QHostAddress::LocalHost<<" and the port "<<port;
            //Return = false;
        }
    }
else
    {
        qDebug()<<"Failed to bind socket to the address "<<QHostAddress::LocalHost<<" and the port "<<port;
        //Return = false;
    }

其次,如果出现问题,Qt中的套接字会发出错误信号。所以你应该有一个插槽来捕获这些错误信号。通过这种方式,您可以了解问题背后的原因。

例如:

connect(udpsocket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(onSocketError(QAbstractSocket::SocketError)));

接收socker错误的插槽:

void SomeInterface::onSocketError(QAbstractSocket::SocketError socketError)
{
    qDebug()<<"socket error occured and the error is : "<<socketError;
}