【问题标题】:c++ QT QUdp socket not sending / receiving data?c++ QT QUdp套接字不发送/接收数据?
【发布时间】:2016-10-23 21:54:49
【问题描述】:

根据这个页面https://wiki.sa-mp.com/wiki/Query_Mechanism我可以向主机发送一些数据,它会回复一些信息给我,对吗? 如果没有,如果有人可以帮助我,我将不胜感激。

但是我正在执行以下代码,但它只是简单地什么都不做 O.O 有人知道我在做什么错吗?

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QUdpSocket>
#include <qmessagebox.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QUdpSocket *mysock = new QUdpSocket(this);
    mysock->writeDatagram("i", QHostAddress("164.132.69.65"), 7777);
    QByteArray myarry;
    QHostAddress myhost;
    quint16 port;
    mysock->readDatagram(myarry.data(), myarry.size(), &myhost, &port);
    ui->textEdit->setText(myarry.data());
}

MainWindow::~MainWindow()
{
    delete ui;
}        

myarry.data() 只是简单的空;-;....

【问题讨论】:

  • 您必须返回事件循环才能完成数据报的发送。在您进行读取时,它仍在输出缓冲区中,等待发送。

标签: c++ qt sockets udp


【解决方案1】:

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 的定义,仅此而已)。

【讨论】:

  • 我已经尝试过你的代码,但 readPendingDatagrams 永远不会被调用...:'c
  • 你确定另一端是真的发回任何东西吗?请使用像wireshark这样的嗅探器工具来确认。您正在使用 UDP,无法保证某些主机确实存在于 "164.132.69.65" 并且它已收到您发送的数据报。
  • 主机没有问题,我已经在 c# 中制作了一个应用程序,它可以毫无问题地获取信息,它工作得很好!,我知道 c++ 有什么问题:'c
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-01
  • 2013-03-06
  • 2010-11-13
  • 2017-01-12
  • 2014-11-25
  • 2017-09-27
  • 2013-06-18
相关资源
最近更新 更多