本次记录了两Qsocket的问题。
问题一描述:
QUDP一开始就接收不到数据,通过bool打印connect是成功连接的,readyRead也响应,但就是收不到数据。
UdpCommunication::UdpCommunication(QObject *parent)
:QObject(parent)
{
udpSocket = new QUdpSocket(this);
qint16 port;
port = 8806;
udpSocket->bind(QHostAddress::AnyIPv4,8806);
connect(udpSocket, &QUdpSocket::readyRead, this, &UdpCommunication::unicastRev);
}
1.1最终找到了问题所在:
原因是调用 writeDatagram() 发送数据包时,程序不知道有没有发完,会一直指向这里,相当于阻塞了。
即使socket信号readyRead()发送了,也不会调用接收函数readDatagram();所以导致接收端一直接收不到数据。
需要在发送的时候调用udpSocket->waitForReadyRead(100);告诉程序发送完毕。目前发现在windows下会出现这个问题。
1.2示例:
UdpCommunication::UdpCommunication(QObject *parent)
:QObject(parent)
{
udpSocket = new QUdpSocket(this);
qint16 port;
port = 8806;
udpSocket->bind(QHostAddress::AnyIPv4,port );//绑定本机发送的端口,否则随机端口发送
udpSocket->bind(port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);//绑定本机端口
connect(udpSocket, &QUdpSocket::readyRead, this, &UdpCom::unicastRev);
}
//发送
udpSocket->writeDatagram((char *)sendBuff, 2, QHostAddress::Broadcast, CONNECT_PORT_SEND);
udpSocket->waitForReadyRead(100);//结束发送,等待读取
//接收
QByteArray array;
QHostAddress address;
quint16 port;
array.resize(udpSocket->bytesAvailable());//根据可读数据来设置空间大小
udpSocket->readDatagram(array.data(),array.size(),&address,&port); //读取数据
问题二描述:
程序运行一段时间,readyRead不响应,无法接收数据的问题。
本人猜测udpsocket缓存接收中,有数据我没有接收完,导致readyRead不响应。
2.1readyRead的触发机制
1)readyRead信号触发是在QTcpSocket缓存接收到新的数据时,并不等同于发送端write函数调用一次。
2)当数据从系统缓冲区到QTcpSocket缓存时,readyRead信号触发一次。如果此时readyRead槽函数还没有及时执行,又有新的数据到来了,而且来了很多次(QTcpSocket缓存还没满的情况,满的情况下系统不再发数据给应用),那么这些所有的都将会只触发一次readyRead信号。
3)当数据从系统缓冲区到QTcpSocket缓存时,readyRead信号触发一次。如果此时readyRead槽函数执行了,后续再来的新数据,将会触发新的readyRead信号。但这个QTcpSocket连接中,还没有响应的readyRead信号最多只有两个。
2.2于是在这次问题的解决办法是:
关闭连接,重新建立连接。
if(udpsocket->bytesAvailable()!=0)
{
qDebug()<<"接收不到数据,重启";
udpsocket->close ();
udpsocket=new QUdpSocket(this);
udpsocket->bind (1234,QUdpSocket::ShareAddress);
connect (udpsocket,&QUdpSocket::readyRead,this,&UdpCom::unicastRev);
}
若接收数据正常,udpsocket->bytesAvailable()的值将为0,接收不到数据则为非零值,这样就可用个定时器,循环检测下,若不为零,将SOCKET重启即可。
虽然挖到了QUDP的比较底层的原理,其实我感觉这个解决办法并没有解决根本原因,如果真的是缓存有数据没取完,是什么原因造成的,还得继续深挖。怎么说呢,这个问题也算是解决完了,不然一直卡着也不行。