QUdpSocket::readDatagram()(以及大多数 Qt 网络 IO 功能)在数据可用之前不阻塞。这意味着,如果您在没有数据到达的地方调用它,您提供的缓冲区中将没有任何数据,调用应该返回-1。
来自docs:
每当数据报到达时,就会发出readyRead() 信号。在那里面
在这种情况下,hasPendingDatagrams() 返回 true。致电pendingDatagramSize()
获取第一个待处理数据报的大小,以及readDatagram()
阅读它。
您应该从连接到readyRead() 信号的插槽调用readDatagram()。
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//mysock should be a member of the MainWindow class
//so that you can access it from other functions
mysock = new QUdpSocket(this);
mysock->writeDatagram("i", QHostAddress("164.132.69.65"), 7777);
connect(mysock, &QUdpSocket::readyRead, this, &MainWindow::readPendingDatagrams);
}
//add this slot to the class's declaration
void MainWindow::readPendingDatagrams(){
//read datagrams in a loop to make sure that all received datagrams are processed
//since readyRead() is emitted for a datagram only when all previous datagrams are read
while(mysock->hasPendingDatagrams()){
QByteArray datagram;
datagram.resize(mysock->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
mysock->readDatagram(datagram.data(), datagram.size(),
&sender, &senderPort);
//do whatever you want to received datagram
ui->textEdit->setText(datagram.data());
}
}
编辑:
看起来您发送到服务器的请求不符合your link 中的规范。在您的代码中,您只是发送一封"i" 信函,没有其他内容。
该页面表示(简要地)您应该发送前缀"SAMP",后跟服务器的IP,然后是服务器的端口,之后您可以发送您的操作码(在您的情况下为"i")。
总而言之,这就是我将如何实现它:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//mysock should be a member of the MainWindow class
//so that you can access it from other functions
mysock = new QUdpSocket(this);
QHostAddress serverAddress("164.132.69.65");
quint16 port= 7777;
QByteArray data;
//building request
data+= "SAMP"; //"SAMP" prefix
//convert to big endian to make sure the octets are sent in the specified order
quint32 ipv4AddrBigEndian= qToBigEndian(serverAddress.toIPv4Address());
//convert to little endian to make sure port bytes are sent in the specified order
quint16 portLittleEndian= qToLittleEndian(port);
//add server ip address
data.append(reinterpret_cast<char*>(&ipv4AddrBigEndian), sizeof(ipv4AddrBigEndian));
//add server port
data.append(reinterpret_cast<char*>(&portLittleEndian), sizeof(portLittleEndian));
//add opcode
data.append("i");
mysock->writeDatagram(data, serverAddress, port);
connect(mysock, &QUdpSocket::readyRead, this, &MainWindow::readPendingDatagrams);
}
void MainWindow::readPendingDatagrams(){
//read datagrams in a loop to make sure that all received datagrams are processed
//since readyRead() is emitted for a datagram only when all previous datagrams are read
while(mysock->hasPendingDatagrams()){
QByteArray datagram;
datagram.resize(mysock->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
mysock->readDatagram(datagram.data(), datagram.size(),
&sender, &senderPort);
qDebug() << "received: " << datagram.toHex();
//do whatever you want to received datagram
//you need to parse information you want from the datagram
//It can NOT be just displayed as text in a QTextEdit (as it contains binary data)
}
}
您需要解析的服务器二进制回复的格式在您链接的页面here中指定。
旁注:
我真的认为你应该在它们自己的类中分离构建请求和解析响应,而不是将所有这些都放在 MainWindow 类中(应该用于 UI 的定义,仅此而已)。