查看完整版本: [-- QT网络通信   UDP广播+多线程问题 --]

QTCN开发网 -> Qt基础编程 -> QT网络通信   UDP广播+多线程问题 [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

suzhuorui 2019-08-14 20:36

QT网络通信   UDP广播+多线程问题

程序A中每次创建5个线程发送广播       但是程序B每次只能接收到2个。代码就是最简单的测试代码,求大佬告知问题所在

[attachment=20698][attachment=20699][attachment=20700][attachment=20701][attachment=20702]

firebolt 2019-08-14 22:09
不明白广播为啥要用5个线程,如果是测试多线程需要给udpSocket加个锁。

yunchao630 2019-08-15 08:36
同上,发送广播的函数互斥一下

suzhuorui 2019-08-15 14:12
firebolt:不明白广播为啥要用5个线程,如果是测试多线程需要给udpSocket加个锁。 (2019-08-14 22:09) 

加锁的话,我是在run函数中加的,也没用呀
如果我想让 for循环中的5个线程 依次发送广播,就是等待第一个线程发送完毕再开始第二个线程,要怎么办呢?

suzhuorui 2019-08-15 14:28
suzhuorui:加锁的话,我是在run函数中加的,也没用呀
如果我想让 for循环中的5个线程 依次发送广播,就是等待第一个线程发送完毕再开始第二个线程,要怎么办呢? (2019-08-15 14:12) 

用计时器可以做到    但是用for循环怎么做呢?求大神指点

powerriver 2019-08-20 22:52
使用信号/槽,不要使用循环的方式,在初始化时
    udpsocket = new QUdpSocket(this);
    bool ret = udpsocket->bind(port, QUdpSocket::ShareAddress|QUdpSocket::ReuseAddressHint);
    if (!ret)
        exit(0);
    connect(udpsocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));

void Mainwindow::readPendingDatagrams()
{
    while(udpsocket->hasPendingDatagrams())
    {
     .....

suzhuorui 2019-08-21 09:47
powerriver:使用信号/槽,不要使用循环的方式,在初始化时
    udpsocket = new QUdpSocket(this);
    bool ret = udpsocket->bind(port, QUdpSocket::ShareAddress|QUdpSocket::ReuseAddressHint);
    if (!ret)
 &n .. (2019-08-20 22:52) 

我循环只是为了多开线程,而且我也有用到信号槽
我就是想测试一下这个广播,想看看一下子发送的人数多了(就是循环五次开了五个线程) ,   能不能全部接到,但结果是不能的,我也不知道问题出在哪里,所以.......大佬

青空飞羽 2019-08-21 11:18
UdpSend中的udpSocket应该放在run方法里去new吧,这样udpSocket才是属于线程,放到构造函数里new的话还是属于主线程

suzhuorui 2019-08-21 16:13
青空飞羽:
UdpSend中的udpSocket应该放在run方法里去new吧,这样udpSocket才是属于线程,放到构造函数里new的话还是属于主线程

青空飞羽:
UdpSend中的udpSocket应该放在run方法里去new吧,这样udpSocket才是属于线程,放到构造函数里new的话还是属于主线程

放进去了,但还是不可以。

我在run函数中加入了一个全局变量,并且加锁看了一下,现在的问题是在第一次点击发送广播按钮后只能接收到0和4,而接下来的每一次都能接收到5次正确的值,这是为什么呢?
[attachment=20743][attachment=20744][attachment=20745]



suzhuorui 2019-08-22 09:56
问题解决了,上完整的代码

发送端界面cpp
  1. #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QUdpSocket>
    #include "udpsend.h"
    #include <QMutex>


    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
          ui->setupUi(this);
    }


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


    int num=0;
    QMutex mutex;


    void MainWindow::on_pushButton_clicked()
    {
          UdpSend *thread[5];
          for(int i=0;i<5;i++)
          {
                mutex.lock();
                qDebug()<<i;
                thread[i]=new UdpSend();
                connect(thread[i],SIGNAL(finished()),this,SLOT(deleteLater()));
                thread[i]->start();
          }
    }





发送端线程cpp    
UdpSend线程类
  1. [color=#000000]#include "udpsend.h"[/color]
    [color=#000000]#include <QMutex>[/color]
    [color=#000000]UdpSend::UdpSend(QObject *parent) : QThread(parent)[/color]
    [color=#000000]{[/color]


    [color=#000000]}[/color]


    [color=#000000]extern int num;[/color]
    [color=#000000]extern QMutex mutex;[/color]


    [color=#000000]void UdpSend::run()[/color]
    [color=#000000]{[/color]
    [color=#000000]    myUdpSocket=new QUdpSocket(this);[/color]
    [color=#000000]    QString data="广播"+QString::number(num);[/color]
    [color=#000000]    num++;[/color]
    [color=#000000]    myUdpSocket->writeDatagram(data.toUtf8(),QHostAddress::Broadcast,quint16(5555));[/color]
    [color=#000000]    mutex.unlock();[/color]
    [color=#000000]    exec();[/color]
    [color=#000000]}[/color]





接收端cpp


  1. #include "mainwindow.h"
    #include "ui_mainwindow.h"


    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
          ui->setupUi(this);
          udpsocket=new QUdpSocket(this);
          udpsocket->bind(QHostAddress::AnyIPv4,quint16(5555));
          connect(udpsocket,SIGNAL(readyRead()),this,SLOT(ricv_msg()));
    }


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


    void MainWindow::ricv_msg()
    {
          QHostAddress sendID;
          quint16 sendport;
          QByteArray data;
          if(udpsocket->hasPendingDatagrams())
          {
                data.resize(udpsocket->pendingDatagramSize());
                udpsocket->readDatagram(data.data(),data.size(),&sendID,&sendport);
          }
          QString str="发送端的IP:"+sendID.toString()+"  端口号:"+QString::number(sendport)+"  内容:"+data;
          ui->textBrowser->append(str);
    }



总结一下
1.首先使用循环创建多线程时需要加锁
2.在接收端的接收函数不要使用while(udpsocket->hasPendingDatagrams()),而要用if(udpsocket->hasPendingDatagrams())
3.接收数据的大小不能用data.resize(udpsocket->bytesAvailable());,而要用data.resize(udpsocket->pendingDatagramSize());,否则可能会有接收大小不一致,会导致出现意外乱码

以上代码为我个人意见,若有问题请指出来共同进步

fsu0413 2019-08-23 08:33
suzhuorui:问题解决了,上完整的代码
发送端界面cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
....... (2019-08-22 09:56) 

用if肯定是错的,应该用while,后面的处理应该放到while里

suzhuorui 2019-08-23 14:34
fsu0413:用if肯定是错的,应该用while,后面的处理应该放到while里 (2019-08-23 08:33) 

卧槽,我试了一下,果然可以。想了想if是只执行一次,while是可以接收一个用户的多个包。谢谢大佬指出错误


查看完整版本: [-- QT网络通信   UDP广播+多线程问题 --] [-- top --]



Powered by phpwind v8.7 Code ©2003-2011 phpwind
Gzip disabled