我通常在这里使用这种方法发送自己的UDP数据包:
How to receive proper UDP packet in QT?
我正在设置模式,以便在写入模式下,它每秒发送UDP数据包,在读取模式下,它只接收数据包。为此,我设置了一个名为readmode
的简单布尔变量,当readmode = true
时,它在= false
时读取和写入。我离开了connect(socket, SIGNAL(readyRead()), this,SLOT(readyRead()));
并调用了MainWindow
构造函数中的send函数,并将if
语句,测试readMode
的状态实际上做了一些事情,在send函数和readyRead()
函数本身。
我的问题是,在打开程序写入窗口之前,每当我以读取模式启动程序时,我才会收到数据包。如果我在打开Read程序之前开始发送数据包,我什么也得不到。
为了澄清,我打开了这个程序的两个实例,我将一个设置为Read,另一个设置为Write,但是必须首先启动Read以使其工作,但是一旦状态发生变化,它就会停止工作。
我怎么能一直读它呢?
代码示例:
bool readMode = true; //Write mode = false, Read Mode = true
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
timer = new QTimer(this);
timer->start(1000);
ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Read");
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText("Write");
out_socket = new QUdpSocket(this);
out_socket->bind(60500);
in_socket = new QUdpSocket(this);
in_socket->bind(60510);
connect(timer, SIGNAL(timeout()),this,SLOT(UDP_test()));
connect(in_socket,SIGNAL(readyRead()),this,SLOT(readyRead()));
}
void MainWindow::UDP_test() //Write Mode
{
if (readMode == false) //Write Mode
{
QByteArray Data;
Data.append(fullResultString);
out_socket->writeDatagram(Data,QHostAddress("192.168.127.10"),60510);
}
void MainWindow::readyRead() //Read Mode
{
if (readMode == true) //Readmode
{
while(in_socket->hasPendingDatagrams())
{
QByteArray UDPBuffer;
UDPBuffer.resize(in_socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
in_socket->readDatagram(UDPBuffer.data(),UDPBuffer.size(), &sender, &senderPort);
}
这是预期的:每次调用进程都会尝试绑定输入套接字。第一次,套接字没有绑定 - 它成功了。第二次 - 它失败了,因为端口已经绑定 - 所以读取不起作用。除了一切,代码永远不会检查错误,从而让用户(即你)不知道事情已经失败。通过错误检查,很明显为什么它不起作用。输出套接字不需要绑定到显式指定的端口号。只有在程序处于接收模式时才能绑定输入套接字。
如果QUdpSocket在收到新数据报时已经包含(未读取)数据报,则它不会发出readyRead。您的源代码未完成。所以我们看不出你如何改变你的全局变量'readMode'。
这里简单的演示应用程序:
#include <QApplication>
#include <QWidget>
#include <QUdpSocket>
#include <QPushButton>
#include <QListWidget>
#include <QGridLayout>
#include <QDebug>
#include <QUuid>
int main( int argc, char** argv ) {
QApplication app( argc, argv );
QWidget form;
auto*const log_widget = new QListWidget( &form );
auto*const client = new QUdpSocket( qApp );
auto*const server = new QUdpSocket( qApp );
const quint16 TEST_PORT = 31088;
if( ! server->bind( QHostAddress::LocalHost, TEST_PORT ) ) {
exit( 1 );
}
QObject::connect( server, &QUdpSocket::readyRead, [=]() {
log_widget->insertItem( 0, "readyRead() has been received" );
});
auto*const write_button = new QPushButton( "&Write", &form );
QObject::connect( write_button, &QPushButton::clicked, [=]() {
const auto packet = QUuid::createUuid().toByteArray();
client->writeDatagram( packet, QHostAddress::LocalHost, TEST_PORT );
log_widget->insertItem( 0, "A datagram has been sent." );
});
auto*const read_button = new QPushButton( "&Read", &form );
QObject::connect( read_button, &QPushButton::clicked, [=]() {
if( server->hasPendingDatagrams() ) {
const int size = static_cast< int >( server->pendingDatagramSize() );
if( size > 0 ) {
QByteArray packet;
packet.resize( size );
server->readDatagram( packet.data(), size );
log_widget->insertItem( 0, "Read OK: datagram have been read." );
} else {
log_widget->insertItem( 0, "Read Error: invalid datagram size." );
}
} else {
log_widget->insertItem( 0, "Read Error: there is no any datagram." );
}
});
auto*const check_button = new QPushButton( "&Check", &form );
QObject::connect( check_button, &QPushButton::clicked, [=]() {
if( server->hasPendingDatagrams() ) {
log_widget->insertItem( 0, "Check: there is at least one datagram." );
} else {
log_widget->insertItem( 0, "Check: there is no any datagram." );
}
});
auto*const grid = new QGridLayout( &form );
grid->addWidget( write_button, 0, 0 );
grid->addWidget( read_button, 0, 1 );
grid->addWidget( check_button, 0, 2 );
grid->addWidget( log_widget, 1, 0, 1, 3 );
form.show();
return app.exec();
}