我必须通过UDP与某些设备通信。问题是如果没有QUdpSocket的特殊情况,bind()根本不起作用。我使用connectToHost()方法for access to read()/write() functions。
使用代码时,UDP交换完全不起作用:
m_udp.connectToHost(QHostAddress("192.168.100.15"), 4001);
m_udp.waitForConnected();
我没有收到任何字节。 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();
为什么这种行为如此奇怪?怎么能理解这个?
答案 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;
}