使用UDP协议和readDatagram接收数据 [英] Receive data with UDP protocol and readDatagram

查看:2719
本文介绍了使用UDP协议和readDatagram接收数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在帮助我使用UDP协议向某人正确发送数据的第一个主题后,我在接收这些数据时遇到问题。这个问题很奇怪,只发生在我第一次启动发送数据的功能。第一次,服务器只接收第一帧。



下面是通过UDP协议发送数据的代码(我的数据是一个结构体):

  void MyUDP :: sendUDP()
{
//发送结构
typedef struct MyStructTag
{
int test1;
bool test2;
char test3;
} MyStruct;

MyStruct envoie;

envoie.test1 = 1;
envoie.test2 = true;
envoie.test3 = 97;

//将数据报数据报
//发送到主机地址和端口。
// qint64 QUdpSocket :: writeDatagram(const QByteArray& datagram,
// const QHostAddress& host,quint16 port)

QByteArray buf;
QDataStream s(& buf,QIODevice :: WriteOnly);
//默认情况下,所有系统上的编码都是big endian。你
//可以改变它,如果你愿意。
if(false)s.setByteOrder(QDataStream :: LittleEndian);
s<< (qint32)envoie.test1<< (quint8)envoie.test2< (qint8)envoie.test3;

//我发送5帧

socket-> writeDatagram(buf,QHostAddress(10.100.14.79),4000);
socket-> writeDatagram(buf,QHostAddress(10.100.14.79),4000);
socket-> writeDatagram(buf,QHostAddress(10.100.14.79),4000);
socket-> writeDatagram(buf,QHostAddress(10.100.14.79),4000);
socket-> writeDatagram(buf,QHostAddress(10.100.14.79),4000);
}

这里的函数允许我接收这些数据:

  void MyUDP :: readyRead()
{

QHostAddress sender;
quint16 senderPort;

// qint64 QUdpSocket :: readDatagram(char * data,qint64 maxSize,
// QHostAddress * address = 0,quint16 * port = 0)
//接收数据报不大于maxSize字节并将其存储在数据中。
//发件人的主机地址和端口存储在* address和* port
//(除非指针为0)。

typedef struct MyStructTag
{
int test1;
bool test2;
char test3;

} MyStruct;

MyStruct recois;
socket-> readDatagram((char *)& recois,sizeof(recois),& sender,& senderPort);


qDebug()<< Message from:<< sender.toString();
qDebug()<< 消息端口:< senderPort;
qDebug()<< Message:<< recois.test3;
}

为什么我第一次启动sendUDP时只收到1帧? p>

解决方案

有两个问题:


  1. readyRead 中,您必须循环 socket-> hasPendingDatagrams()

    必须在发送时使用 QDataStream 和接收端。


最后,您正在编写C ++,不应使用C结构语法。使结构声明重复也是适得其反。您需要的是让 MyStruct

$>的流运算符。



下面是一个完整的示例。

  #include< QCoreApplication> 
#include< QUdpSocket>
#include< QDataStream>
#include< QBasicTimer>

static const quint16 port = 4000;

class MyUDP:public QObject {
Q_OBJECT
QUdpSocket m_socket;
QBasicTimer m_timer;

void timerEvent(QTimerEvent * ev){
if(ev-> timerId()!= m_timer.timerId())return;
sendUDP();
}
void sendUDP();
public:
MyUDP(){
m_timer.start(1000,this);
connect(& m_socket,SIGNAL(readyRead()),SLOT(readyRead()));
m_socket.bind(QHostAddress :: LocalHost,port);
}
Q_SLOT void readyRead();
};

struct MyStruct {
int test1;
bool test2;
char test3;
MyStruct(){}
MyStruct(int t1,bool t2,char t3):test1(t1),test2(t2),test3(t3){}
};

template< typename T> T get(QDataStream& str){
T value;
str>>值;
返回值;
}

QDataStream& operator<<<(QDataStream& str,const MyStruct& m)
{
return str< (qint32)m.test1 < (bool)m.test2 < (qint8)m.test3;
}

QDataStream& >>(QDataStream& str,MyStruct& m)
{
m.test1 = get< qint32>(str);
m.test2 = get< bool>(str);
m.test3 = get< qint8>(str);
return str;
}

void MyUDP :: sendUDP()
{
MyStruct envoie(1,true,97);

QByteArray buf;
QDataStream s(& buf,QIODevice :: WriteOnly);
//默认情况下,所有系统上的编码都是big endian。你
//可以改变它,如果你愿意。
if(false)s.setByteOrder(QDataStream :: LittleEndian);
s<<恩沃伊

for(int i = 0; i <5; ++ i){
m_socket.writeDatagram(buf,QHostAddress :: LocalHost,port);
}
}

void MyUDP :: readyRead()
{
QHostAddress sender;
quint16 senderPort;

MyStruct recois;
while(m_socket.hasPendingDatagrams()){
QByteArray buf(m_socket.pendingDatagramSize(),Qt :: Uninitialized);
QDataStream str(& buf,QIODevice :: ReadOnly);
m_socket.readDatagram(buf.data(),buf.size(),& sender,& senderPort);
str>>雷西斯
qDebug()<< Message from:<<发送者
qDebug()<< 消息端口:< senderPort;
qDebug()<< Message:<< recois.test3;
}
}

int main(int argc,char * argv [])
{
QCoreApplication a(argc,argv);
MyUDP udp;
return a.exec();
}

#includemain.moc


After a first topic that help me send correctly data to someone using UDP Protocol, I have a problem in the reception of these data. This problem is very strange and only happen the first time I launch the function for sending data. The first time, the server only receive the first frame. But after, if I re use the function everything is ok.

So here's the code that send data through UDP Protocol (my data is a structure) :

void MyUDP::sendUDP()
{
    //Structure to send
    typedef struct MyStructTag
    {
       int test1;
       bool test2;
       char test3;
    } MyStruct;

    MyStruct envoie;

    envoie.test1 = 1;
    envoie.test2 = true;
    envoie.test3 = 97;

    // Sends the datagram datagram
    // to the host address and at port.
    // qint64 QUdpSocket::writeDatagram(const QByteArray & datagram,
    //                      const QHostAddress & host, quint16 port)

    QByteArray buf;
    QDataStream s(&buf, QIODevice::WriteOnly);
    // The encoding is big endian by default, on all systems. You
    // can change it if you wish.
    if (false) s.setByteOrder(QDataStream::LittleEndian);
    s << (qint32)envoie.test1 << (quint8)envoie.test2 << (qint8)envoie.test3;

    //I'm sending 5 frames        

    socket->writeDatagram(buf, QHostAddress("10.100.14.79"), 4000);
    socket->writeDatagram(buf, QHostAddress("10.100.14.79"), 4000);
    socket->writeDatagram(buf, QHostAddress("10.100.14.79"), 4000);
    socket->writeDatagram(buf, QHostAddress("10.100.14.79"), 4000);
    socket->writeDatagram(buf, QHostAddress("10.100.14.79"), 4000);
}

And here's the function that allow me te receive these data :

void MyUDP::readyRead()
{

    QHostAddress sender;
    quint16 senderPort;

    // qint64 QUdpSocket::readDatagram(char * data, qint64 maxSize,
    //                 QHostAddress * address = 0, quint16 * port = 0)
    // Receives a datagram no larger than maxSize bytes and stores it in data.
    // The sender's host address and port is stored in *address and *port
    // (unless the pointers are 0).

    typedef struct MyStructTag
    {
       int test1;
       bool test2;
       char test3;

    } MyStruct;

    MyStruct recois;
    socket->readDatagram((char*)&recois, sizeof (recois), &sender, &senderPort);


    qDebug() << "Message from: " << sender.toString();
    qDebug() << "Message port: " << senderPort;
    qDebug() << "Message: " << recois.test3;
}

Why did I only receive 1 frame the first time I launch sendUDP ?

解决方案

There are two problems:

  1. Within the readyRead you must loop while socket->hasPendingDatagrams() is true.

  2. You must use the QDataStream on both the sending and the receiving end.

Finally, you are writing C++, you should not use the C structure syntax. It is also counterproductive to have the structure declaration duplicated. What you need is to have the streaming operators for MyStruct.

Below is a complete example.

#include <QCoreApplication>
#include <QUdpSocket>
#include <QDataStream>
#include <QBasicTimer>

static const quint16 port = 4000;

class MyUDP : public QObject {
   Q_OBJECT
   QUdpSocket m_socket;
   QBasicTimer m_timer;

   void timerEvent(QTimerEvent*ev) {
      if (ev->timerId() != m_timer.timerId()) return;
      sendUDP();
   }
   void sendUDP();
public:
   MyUDP() {
      m_timer.start(1000, this);
      connect(&m_socket, SIGNAL(readyRead()), SLOT(readyRead()));
      m_socket.bind(QHostAddress::LocalHost, port);
   }
   Q_SLOT void readyRead();
};

struct MyStruct {
   int test1;
   bool test2;
   char test3;
   MyStruct() {}
   MyStruct(int t1, bool t2, char t3) : test1(t1), test2(t2), test3(t3) {}
};

template <typename T> T get(QDataStream & str) {
   T value;
   str >> value;
   return value;
}

QDataStream & operator<<(QDataStream & str, const MyStruct & m)
{
   return str << (qint32)m.test1 << (bool)m.test2 << (qint8)m.test3;
}

QDataStream & operator>>(QDataStream & str, MyStruct & m)
{
   m.test1 = get<qint32>(str);
   m.test2 = get<bool>(str);
   m.test3 = get<qint8>(str);
   return str;
}

void MyUDP::sendUDP()
{
   MyStruct envoie(1, true, 97);

   QByteArray buf;
   QDataStream s(&buf, QIODevice::WriteOnly);
   // The encoding is big endian by default, on all systems. You
   // can change it if you wish.
   if (false) s.setByteOrder(QDataStream::LittleEndian);
   s << envoie;

   for (int i = 0; i < 5; ++ i) {
      m_socket.writeDatagram(buf, QHostAddress::LocalHost, port);
   }
}

void MyUDP::readyRead()
{
   QHostAddress sender;
   quint16 senderPort;

   MyStruct recois;
   while (m_socket.hasPendingDatagrams()) {
      QByteArray buf(m_socket.pendingDatagramSize(), Qt::Uninitialized);
      QDataStream str(&buf, QIODevice::ReadOnly);
      m_socket.readDatagram(buf.data(), buf.size(), &sender, &senderPort);
      str >> recois;
      qDebug() << "Message from: " << sender;
      qDebug() << "Message port: " << senderPort;
      qDebug() << "Message: " << recois.test3;
   }
}

int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   MyUDP udp;
   return a.exec();
}

#include "main.moc"

这篇关于使用UDP协议和readDatagram接收数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆