您的位置:首页 > 编程语言 > Qt开发

QUdpSocket收不到回复及分析

2016-03-09 16:09 417 查看
QT中使用QUdpSocket发送数据给服务器,然后通过readyread信号读取回复。

init:
udp=new QUDPSocket()
connect(udp,SIGNAL(readyread()),this,SLOT(processread()));

work:
udp->writedatagram


实际情况是:数据能够发送出去,服务器返回的数据却无法触发readyread信号。

实验后,如下代码能够正常接收

init:
udp=new QUDPSocket()
connect(udp,SIGNAL(readyread()),this,SLOT(processread()));
udp->connectToHost()

work:
udp->write


或者

init:
udp=new QUDPSocket()
connect(udp,SIGNAL(readyread()),this,SLOT(processread()));
udp->bind()

work:
udp->writeDataGram


按照帮助文档,The most common way to use this class is to bind to an address and port using bind(), then call writeDatagram() and readDatagram() to transfer data. If you just want to send datagrams, you don’t need to call bind().

也就是说一般需要绑定,若只是发送数据不需要接收,则可以不绑定。

分析源码:

QT的编码风格是,每个可导出的类都有一个隐藏的实现类,例如QUDPSocket有一个实现类QUDPSocketPrivate,大部分的代码逻辑都是在隐藏类中实现的。

QUDPSocket继承关系:QUDPSocket->QAbstractSocket->QIODevice,QAbstractSocketEngineReceiver

QUDPSocketPrivate继承关系:QUDPSocketPrivate->QAbstractSocketPrivate->QIODevicePrivate,QAbstractSocketEngineReceiver.

其中QAbstractSocketPrivate中有一个重要的元素,QAbstractSocketEngine engine,不同的平台有不同的实现,例如linux平台实现类为QNativeSocketEngine_unix。 engine实现的逻辑就是调用像connect, send, recv这样标准的socket编程接口。

QNativeSocketEngine中保存了一个QReadNotify成员(继承QSocketNofity)

void QNativeSocketEngine::setReadNotificationEnabled(bool enable)
{
...
d->readNotifier=new QReadNotifier(d->socketDescriptor,this);
...
}


QReadNotifier继承QSocketNotifier检车SockAct事件(QWriteNotifier和QExceptionNotifier类似)

bool QReadNotifier::event(QEvent* e)
{
if(e->type()==QEvent::SockAct){
engine->readNofication();
}
return QSocketNotifier::event(e);
}


readNotification会告知QSocketEngineReceiver

void QAbstractSocketEngine::readNotification()
{
receiver->readNotification();
}


其中receiver是QSocketEngineReceiver类型,在QAbstractSocketEngine构造函数中被告知。readNotification是一个虚函数,在QAbstractSocketPrivate中定义,所以,实际上调用的是:

QAstractSocketPrivate::canReadNotification()
{
...
emit q->readyRead();
...
}


q指向的QAbstractSocket导出类对象

为什么bind会影响数据的接收?

原因在于bind开启了ReadNotification

bool QUdpSocket::bind(..)
{
...
d_func()->socketEngine->setReadNotificationEnabled(true);
...
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  qt