QUdpSocket无法将消息从服​​务器正确发送到客户端

时间:2019-02-22 15:49:05

标签: c++ qt5 qudpsocket

我正在构建用户界面服务器/客户端。为了复制问题,我准备了一个MVCE来复制我遇到的问题。

GUI的描述如下:服务器计算机具有一个QGraphicsView,其中{。{1}}和障碍物的边界内有N.1个绿色方块在移动。 一旦正方形碰到边界或障碍物,服务器计算机应将带有碰撞坐标的消息发送给客户端。

为了运行示例,步骤如下:

1)设置客户端和服务器上的端口号(端口号必须相同)

2)准备要从服务器发送到客户端的消息

3)连接客户端

4)将消息从服​​务器发送到客户端

5)等到正方形碰到边界或障碍物

6)服务器应尽快将冲突的坐标发送给客户端。 (我被困在最后一点)

请参见下图描述

server/client

到目前为止我尝试过的事情

this post看来,从/向服务器计算机发送的消息应该具有优先级。但是,我可以成功地将消息从服​​务器发送到客户端。

还根据this source,为了不丢失应该设置多个数据报的信息。

此外,始终使用the same post的UDP和TCP可能是造成数据丢失的主要原因。

请参见下面的复制问题的代码

UDP客户端

widget.h

QGraphicsScene

widget.cpp

namespace Ui {
class Widget;
}
class QUdpSocket;
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
private slots:
    void on_connectBtn_clicked();
private:
    Ui::Widget *ui;
    QUdpSocket *mSocket;
};
#endif // WIDGET_H

UDP服务器

widget.h

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    mSocket = new QUdpSocket(this);
    setWindowTitle("Client Machine");
    connect(mSocket, &QUdpSocket::readyRead, [&]() {
       if(mSocket->hasPendingDatagrams()) {
           QByteArray datagram;
           datagram.resize(mSocket->pendingDatagramSize());
           mSocket->readDatagram(datagram.data(), datagram.size());
           ui->listWidget->addItem(QString(datagram));
       }
    });
}

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

void Widget::on_connectBtn_clicked()
{
    mSocket->bind(ui->portSpinBoxClient->value(), QUdpSocket::ShareAddress);
}

widget.cpp

#include <QWidget>
#include <QGraphicsItem>
namespace Ui {
class Widget;
}
class QUdpSocket;
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
private slots:
    void on_sendBtn_clicked();
    void on_pushButton_clicked();
private:
    Ui::Widget *ui;
    QUdpSocket *mSocket;
    QGraphicsScene *scene;
    QTimer *timer;
    QGraphicsRectItem *itemRect;
#endif // WIDGET_H

最后是检测到碰撞对象的类:

myitem.h

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    mSocket = new QUdpSocket(this);
    setWindowTitle("Server Machine");

    scene = new QGraphicsScene(this);
    itemRect = new QGraphicsRectItem();

    ui->graphicsView->setScene(scene);
    ui->graphicsView->setRenderHint(QPainter::Antialiasing);
    scene->setSceneRect(-200, -200, 300, 300);

    QBrush darkBrush(Qt::darkRed);
    QPen darkRedPen(Qt::darkRed);
    itemRect = scene->addRect(-100, -100, 30, 100, darkRedPen, darkBrush);
    itemRect->setFlag(QGraphicsItem::ItemIsMovable);

    QPen myPen = QPen(Qt::red);
    QLineF TopLine(scene->sceneRect().topLeft(), scene->sceneRect().topRight());
    QLineF LeftLine(scene->sceneRect().topLeft(), scene->sceneRect().bottomLeft());
    QLineF RightLine(scene->sceneRect().topRight(), scene->sceneRect().bottomRight());
    QLineF Bottom(scene->sceneRect().bottomLeft(), scene->sceneRect().bottomRight());

    scene->addLine(TopLine, myPen);
    scene->addLine(LeftLine, myPen);
    scene->addLine(RightLine, myPen);
    scene->addLine(Bottom, myPen);

    int itemCount = 1;
    for(int i = 0; i < itemCount; i++) {
        MyItem *item = new MyItem();
        scene->addItem(item);
    }
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), scene, SLOT(advance()));
    timer->start(100);
    ui->pushButton->setStyleSheet("QPushButton{ background-color: grey }");
}

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

void Widget::on_sendBtn_clicked()
{
    auto datagram = ui->msgLineEdit->text().toLatin1();
    mSocket->writeDatagram(datagram, QHostAddress::Broadcast,ui->spinBox->value());
}

void Widget::on_pushButton_clicked()
{
    ui->pushButton->setStyleSheet("QPushButton{ background-color: green }");
    ui->pushButton->setText("Stop");
}

myitem.cpp

class MyItem : public QGraphicsItem
{
public:
    MyItem();
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
protected:
    void advance(int phase);
private:
    qreal angle;
    qreal speed;
    void doCollision();
};

#endif // MYITEM_H

预期结果:绿色方块碰到#include "myitem.h" MyItem::MyItem() { angle = (qrand() % 360); setRotation(angle); speed = 5; int startX = 0; int startY = 0; if((qrand() % 1)){ startX = (qrand() % 200); startY = (qrand() % 200); }else{ startX = (qrand() % -100); startY = (qrand() % -100); } setPos(mapToParent(startX, startY)); } QRectF MyItem::boundingRect() const { return QRect(0, 0, 30, 30); } void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QRectF rec = boundingRect(); QBrush brush(Qt::gray); if(scene()->collidingItems(this).isEmpty()){ brush.setColor(Qt::green); // no collision }else{ brush.setColor(Qt::red); // yes collision doCollision(); } painter->fillRect(rec, brush); painter->drawRect(rec); } void MyItem::advance(int phase) { if(!phase) return; QPointF location = this->pos(); setPos(mapToParent(0, -(speed))); } void MyItem::doCollision() { if((qrand() %1)) { setRotation(rotation() + (180+(qrand() % 10))); }else{ setRotation(rotation() + (180+(qrand() % -10))); } // see if the new position is in bounds QPointF newPoint = mapToParent(-(boundingRect().width()), -(boundingRect().width() + 2)); if(!scene()->sceneRect().contains((newPoint))){ newPoint = mapToParent(0, 0); // move it back in bounds }else{ setPos(newPoint); // set new position } } 或对象的边界后,应将碰撞坐标发送给客户端。

实际结果:如何将冲突坐标发送给客户?

任何有关如何解决此问题的见解都将非常有用。

0 个答案:

没有答案