1

我必须通过 UDP 与某些设备通信。问题是QUdpSocket在没有特殊情况的情况下根本不起作用bind()。我使用connectToHost()方法来访问 read()/write() 函数

使用代码时UDP交换根本不起作用:

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

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

Wireshark 中的 QUdpSocket 错误

下面的代码也不起作用:

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();

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

4

2 回答 2

3

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

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

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

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

只有第三个片段有效,因为在这里您绑定到本地端口 4001 而不指定 IP 地址,然后还发送到远程计算机上的端口 4001。如果您在 中仅指定端口号bind,则 IP 地址将保留为“通配符”,因此您应该将数据包发送到您机器的任何 IP 地址上的该端口号。

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

于 2017-09-13T16:00:24.037 回答
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;
}
于 2017-09-19T14:59:03.383 回答