2017-09-13 310 views
1

我必须通过UDP与某些设备进行通信。问题是QUdpSocket根本不工作,没有bind()的特殊情况。我使用connectToHost()方法for access to read()/write() functions。使用代码时QUdpSocket无法正常工作

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

您还没有表现出对对方的代码,但显然从显示Wireshark的图像,远程端期待您的插座被绑定到端口4001

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

在UDP中,没有这样的东西作为一个实际的连接。当你使用connectToHost你真的onl y指定远程端的IP地址和端口号。应用程序有责任确保远程端发送回正确的端口。这可以通过(a)始终发送到一个特定的端口(显然是在这里完成),或者(b)另一端可以查看数据报实际收到的地址/端口并发送回该端口;换句话说,远程端可以确定它收到的数据报已经从端口64875发送出去,并将其回复给该端口。

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

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

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

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

插槽接收多功能转换插座错误:

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