精华内容
下载资源
问答
  • 2018-01-04 16:31:09

    0 背景

    项目需求,要用Qt接收惯导数据,数据采用UDP传输,在Qt中提供了QUdpSocket类来进行UDP数据报(datagrams)的发送和接收。这里我们还要了解一个名词Socket,也就是常说的“套接字”。 Socket简单地说,就是一个IP地址加一个port端口。因为我们要传输数据,就要知道往哪个机子上传送,而IP地址确定了一台主机,但是这台机子上可能运行着各种各样的网络程序,我们要往哪个程序中发送呢?这时就要使用一个端口来指定UDP程序。所以说,Socket指明了数据报传输的路径。

    为了使惯导数据的接收不影响主页面的响应,创建新线程来不停地读取数据。下面创建一个UDP的接收端程序。新建一个mainwindow工程,在pro文件中添加QT += network,然后执行以下qmake,确保没有问题。新建gnss类,继承QThread,包括gnss.h和gnss.cpp文件。话不多说,直接上代码!

    1 gnss.h

    #ifndef GNSS_H
    #define GNSS_H
    #include <QThread>
    #include <QtCore>
    #include <QObject>
    #include <QMutex>
    #include <iostream>
    #include <QtNetwork>
    
    class GNSS: public QThread
    {
    public:    
        Q_OBJECT
    public:
        GNSS();
        void stop();
    private slots:
        void run();
        void processPendingDatagram();
    private:
        bool stopped;
        QMutex m_lock;
        QUdpSocket *receiver;
        QFile f();
    };
    
    #endif // GNSS_H

    2 gnss.cpp

    #include "gnss.h"
    #include <QTimer>
    #include <QMutexLocker>
    #include "mainwindow.h"
    
    GNSS::GNSS()
    {
    
        stopped = false;//标记可以运行
        //创建一个QUdpSocket类对象,该类提供了Udp的许多相关操作
        receiver = new QUdpSocket(this);
        int port =3000;//设置UDP的端口号参数,指定在此端口上监听数据
        //此处的bind是个重载函数,连接本机的port端口,采用ShareAddress模式(即允许其它的服务连接到相同的地址和端口,特别是
        //用在多客户端监听同一个服务器端口等时特别有效),和ReuseAddressHint模式(重新连接服务器)
        int receive = receiver->bind(QHostAddress("195.0.0.230"),port);
        qDebug() << "receive: " <<receive << endl;
        if(receive == 0)
        {
            qDebug() << "UDP Connected Succeed ! " << endl;
        }
        else
        {
            qDebug() << "UDP Connected Faild ! " << endl;
        }
    }
    void GNSS::stop()
    {
        QMutexLocker locker(&m_lock);
        stopped = true;
        receiver->close();
        delete receiver;
    
    }
    
    void GNSS::run()
    {
        //获得系统时间并输出
        QString min = QDateTime::currentDateTime().toString("yyyyMMddhhmm");
        //打开文本 以时间命名文件名字
        QString fileName = "C:\\SensorsData\\BASLER\\code\\build-opencv-Desktop_Qt_5_8_0_MSVC2015_64bit-Debug\\GNSS_" + min + ".txt";//假设指定文件夹路径为D盘根目录
        QFile f(fileName);
        LONGLONG time_now=0;
        QString s = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
        QString a = QDateTime::currentDateTime().toString("yyyyMMddhhmm");
        QString b = QDateTime::currentDateTime().toString("mmss");
    
        while(!stopped)
        {
            while(receiver->hasPendingDatagrams())  //拥有等待的数据报
            {
               //qDebug() << "receive succeed ! " << endl;
                QByteArray datagram; //拥于存放接收的数据报
               //pendingDatagramSize为返回第一个在等待读取报文的size,
               //resize函数是把datagram的size归一化到参数size的大小一样
               datagram.resize(receiver->pendingDatagramSize());
               //接收数据报,将其存放到datagram中
               //将读取到的不大于datagram.size()大小数据输入到datagram.data()中,
               //datagram.data()返回的是一个字节数组中存储数据位置的指针
               receiver->readDatagram(datagram.data(),datagram.size());
               //将数据报内容显示出来
               QString HexData = datagram.toHex();
               //判断数据是否完整
               if(HexData.length() == 144)
               {
                   //解析Hex数据
                   QString Status = HexData.mid(42,2);
                   qDebug() << "Status :" << Status  << endl;
                   QString Latitude = HexData.mid(46,16);
                   qDebug() << "Latitude :" << Latitude  << endl;
                   QString Longitude = HexData.mid(62,16);
                   qDebug() << "Longitude :" << Longitude  << endl;
                   QString Altitude = HexData.mid(78,8);
                   qDebug() << "Altitude :" << Altitude  << endl;
                   QString North_Velocity = HexData.mid(86,6);
                   qDebug() << "North_Velocity :" << North_Velocity  << endl;
                   QString East_Velocity = HexData.mid(92,6);
                   qDebug() << "East_Velocity :" << East_Velocity  << endl;
                   QString Down_Velocity = HexData.mid(98,6);
                   qDebug() << "Down_Velocity :" << Down_Velocity  << endl;
                   QString Heading = HexData.mid(104,6);
                   qDebug() << "Heading :" << Heading  << endl;
                   QString Pitch = HexData.mid(110,6);
                   qDebug() << "Pitch :" << Pitch  << endl;
                   QString Roll = HexData.mid(116,6);
                   qDebug() << "Roll :" << Roll  << endl;
    
                   //获得系统时间并输出
                   s = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
                   a = QDateTime::currentDateTime().toString("yyyyMMddhhmm");
                   b = QDateTime::currentDateTime().toString("mmss");
                   qDebug() << "min : " <<min<< endl;
                   time_now = b.toLongLong();
                   qDebug() << "time_now: " <<time_now<< endl;
                   //每10分钟保存一次
                   if(time_now % 1000 == 0)
                   {
                       qDebug() << "write again ! " <<time_now<< endl;
                       f.fileName() = "C:\\SensorsData\\BASLER\\code\\build-opencv-Desktop_Qt_5_8_0_MSVC2015_64bit-Debug\\GNSS_" + a + ".txt";
                   }
    
                   qDebug() << "time" << s;
    
                   if(!f.open( QIODevice::Append))
                   {
                       cout << "Open failed." << endl;
                   }
                   QTextStream txtOutput(&f);
                   txtOutput << s <<"$$"<< HexData<< "&&" << endl;
    
                   f.close();
    
               }
               else
               {
                   qDebug() << "The data is not complete !" << endl;
               }
            }
        }
    
    
    }
    /***********GNSS数据处理***********/
    void GNSS::processPendingDatagram()
    {
    
    }
    

    3 mainwindow.cpp

    在ui界面新建两个button,分别是开始接收和停止接收,分别命名为StartGNSSBtn和StopGNSSBtn,然后在mainwindow.cpp中添加对应的槽函数

    /***********开始GNSS数据接收***********/
    void MainWindow::on_StartGNSSBtn_clicked()
    {
        if(!gnss.isRunning())
        {
            gnss.start();
            ui->StartGNSSBtn->setEnabled(false);
            ui->StopGNSSBtn->setEnabled(true);
        }
        else
        {
            qDebug() << "GNSS receive has started !!!" << endl;
    
        }
    
    }
    
    /***********停止GNSS数据接收***********/
    void MainWindow::on_StopGNSSBtn_clicked()
    {
        if(gnss.isRunning())
        {
            gnss.stop();
        }
        ui->StartGNSSBtn->setEnabled(true);
        ui->StopGNSSBtn->setEnabled(false);
    }

    同时要记得在mainwindow.h中添加相关的变量和函数,添加头文件#include "gnss.h"

    private:
        //GNSS相关对象
        GNSS gnss;
        QPushButton *StartGNSSBtn;
        QPushButton *StopGNSSBtn;
    private slots:
        //GNSS相关的槽函数
        void on_StartGNSSBtn_clicked();
        void on_StopGNSSBtn_clicked();

    至此完成在新的线程里接收GNSS数据并初步的分割保存工作,下一步进行解析及显示

    更多相关内容
  • vc多线程接收数据与显示参考, 可以借鉴
  • QT多线程接收串口数据

    千次阅读 2021-06-17 22:16:14
    QT多线程接收串口数据 ** 1.前言 QT多线程的使用,和绝大数人一样,犯了错误(请查阅Qt开发人员( Bradley T. Hughes)Blog中的文章 you are-doing-it-wrong介绍)。为了解决问题,网上查阅学习了几十篇文章,基本都是...

    **

    QT多线程接收串口数据

    **
    1.前言
    QT多线程的使用,和绝大数人一样,犯了错误(请查阅Qt开发人员( Bradley T. Hughes)Blog中的文章 you are-doing-it-wrong介绍)。为了解决问题,网上查阅学习了几十篇文章,基本都是错误的使用方法,或者不完整,未能给予正确的引导。
    为方便后来学习者,少走弯路,于是自己动手写了一下程序,过程不再赘述,只以完整的案例进行教学,内部注释较多,可供大家阅读、思考。

    2.功能作用
    使用多线程,避免上位机软件与单片机等硬件设备高速通讯时,造成软件界面假死、丢包等现象。同时对串口进行了简单的封装,方便调用。本文提供了完整的源代码,方便测试。有较详细的注释方便阅读、思考。编译环境为QT5.8.0,Qt Creator4.2.1

    3.软件测试效果

    在这里插入图片描述
    在这里插入图片描述

    4.基本步骤
    (1)pro文件添加QT5自带的头文件

    QT       += serialport
    

    (2)serialworker.h头文件

    #include "serialworker.h"
    
    SerialWorker::SerialWorker(QSerialPort *ser, QObject *parent) : QObject(parent),serial(ser)
    {
    
    }
    QString SerialWorker::ByteArrayToHexString(QByteArray data)
    {
        QString ret(data.toHex().toUpper());
        int len = ret.length()/2;
        qDebug()<<"收到字节长度为:"<<len;
        for(int i=1;i<len;i++)
        {
            ret.insert(2*i+i-1," ");
        }
        return ret;
    }
    
    void SerialWorker::doDataReciveWork()
    {    
        QByteArray buffer = serial->readAll();
        // 2.进行数据处理
        QString result = ByteArrayToHexString(buffer);
        qDebug() <<  "子线程收到数据:" << result << "线程ID:" << QThread::currentThreadId();
        // 3.将结果发送到主线程
        emit sendResultToGui(result);
    }
    
    

    (3)mainwindow.h文件

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        setWindowTitle("子线程读串口");
        this->setMinimumSize(600,248);
        this->setMaximumSize(1200,496);
    
        InitSerialPortName();
    
        //1.新建串口处理子线程
        SerialWorker *ser = new SerialWorker(&serial_1);
        ser->moveToThread(&serialThread_1);
    
       // 2.连接信号和槽
        QString s;
        connect(&serialThread_1, &QThread::finished, ser, &QObject::deleteLater);           // 线程结束,自动删除对象
        connect(&serial_1, &QSerialPort::readyRead, ser, &SerialWorker::doDataReciveWork); // 主线程通知子线程接收数据的信号
        connect(ser, &SerialWorker::sendResultToGui, this, &MainWindow::handleResults);    // 主线程收到数据结果的信号
      //  connect(ser,SIGNAL(sendResultToGui(QString)), this, SLOT(handleResults(QString)));     //主线程收到数据结果的信号写法2
    
        // 3.开始运行子线程
        serialThread_1.start();                   // 线程开始运行
    }
    
    MainWindow::~MainWindow()
    {
        serialThread_1.quit();
        serialThread_1.wait();
        delete ui;
    }
    
    void MainWindow::InitSerialPortName()
    {
        // 清空下拉框
        ui->box_portName->clear();
    
        //通过QSerialPortInfo查找可用串口
        foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
        {
            QString showName = info.portName();
            qDebug() << showName+info.description();
            ui->box_portName->addItem(showName);
        }
        //波特率
            QStringList baudrateList;
            baudrateList<<"4800"<<"9600"<<"19200"<<"38400"<<"57600"<<"115200";
            ui->box_baudrate->addItems(baudrateList);//添加下拉列表选项
            ui->box_baudrate->setCurrentText("115200");//界面中初始值
        //    ui->box_baudrate->setView(new QListView(this));//该设置是配合qss的,不然item行高设置没效果
        //数据位
            QStringList databitList;
            databitList<<"5"<<"6"<<"7"<<"8";
            ui->box_dataBits->addItems(databitList);
            ui->box_dataBits->setCurrentText("8");
    //      ui->box_dataBits->setView(new QListView(this));
            //校验位
            QStringList parityList;
            parityList<<"无"<<"奇"<<"偶";
            ui->box_parityBit->addItems(parityList);
            ui->box_parityBit->setCurrentText("No");
    //      ui->box_parityBit->setView(new QListView(this));
            //停止位
            QStringList stopbitList;
            stopbitList<<"1"<<"2";
            ui->box_stopBit->addItems(stopbitList);
            ui->box_stopBit->setCurrentText("1");
    //      ui->box_stopBit->setView(new QListView(this));
            //流控制
    //        QStringList flowctrlList;
    //        flowctrlList<<"No"<<"Hardware"<<"Software";
    //        ui->boxFlowControl->addItems(flowctrlList);
    //        ui->boxFlowControl->setCurrentText("No");
          ui->boxFlowControl->setView(new QListView(this));
    }
    
    void MainWindow::on_btn_openPort_clicked()
    {
        if(ui->btn_openPort->text()==QString("打开串口"))
        {
            //设置串口名
            QString portName = (ui->box_portName->currentText()).split(":").at(0);
            qDebug() <<"当前打开串口为:"<<portName;
            serial_1.setPortName(portName);
    
            //设置波特率
            serial_1.setBaudRate(ui->box_baudrate->currentText().toInt());
    
            //设置停止位
            if(ui->box_stopBit->currentText() == "1")
                serial_1.setStopBits(QSerialPort::OneStop);
            else if(ui->box_stopBit->currentText() == "2")
                serial_1.setStopBits(QSerialPort::TwoStop);
    
            //设置数据位数
            if(ui->box_dataBits->currentText() == "8")
                serial_1.setDataBits(QSerialPort::Data8);
            else if(ui->box_dataBits->currentText() == "7")
                serial_1.setDataBits(QSerialPort::Data7);
            else if(ui->box_dataBits->currentText() == "6")
                serial_1.setDataBits(QSerialPort::Data6);
            else if(ui->box_dataBits->currentText() == "5")
                serial_1.setDataBits(QSerialPort::Data5);
    
            //设置奇偶校验
            if(ui->box_parityBit->currentText() == "无")
                serial_1.setParity(QSerialPort::NoParity);
            else if(ui->box_parityBit->currentText() == "偶")
                serial_1.setParity(QSerialPort::EvenParity);
            else if(ui->box_parityBit->currentText() == "奇")
                serial_1.setParity(QSerialPort::OddParity);
    
    //        //设置流控制
    //        serial_1.setFlowControl(QSerialPort::NoFlowControl);
    
            //打开串口
            if(!serial_1.open(QIODevice::ReadWrite))
            {
                QMessageBox::about(NULL, "提示", "无法打开串口!");
                return;
            }
    
            //下拉菜单控件失能
            ui->box_portName->setEnabled(false);
            ui->box_baudrate->setEnabled(false);
            ui->box_dataBits->setEnabled(false);
            ui->box_parityBit->setEnabled(false);
            ui->box_stopBit->setEnabled(false);
    
            ui->btn_openPort->setText(QString("关闭串口"));
    
        }
        else
        {
            //关闭串口
            serial_1.close();
            //下拉菜单控件使能
            ui->box_portName->setEnabled(true);
            ui->box_baudrate->setEnabled(true);
            ui->box_dataBits->setEnabled(true);
            ui->box_parityBit->setEnabled(true);
            ui->box_stopBit->setEnabled(true);
            ui->btn_openPort->setText(QString("打开串口"));
        }
    }
    
    void MainWindow::on_btn_clearText_clicked()
    {
        ui->browser_dataReceive->clear();
    }
    
    void MainWindow::handleResults(const QString &result)
    {
        qDebug() <<  "主线程收到结果数据:" << result << "线程ID:" << QThread::currentThreadId();
        //从界面中读取以前收到的数据
        QString oldString = ui->browser_dataReceive->toPlainText()+'\n';
        oldString = oldString + QString(result);
        //清空以前的显示
        ui->browser_dataReceive->clear();
        //重新显示
        ui->browser_dataReceive->append(oldString);
    }
    
    

    (4)mainwindow.cpp文件

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        setWindowTitle("子线程读串口");
        this->setMinimumSize(600,248);
        this->setMaximumSize(1200,496);
    
        InitSerialPortName();
    
        //1.新建串口处理子线程
        SerialWorker *ser = new SerialWorker(&serial_1);
        ser->moveToThread(&serialThread_1);
    
       // 2.连接信号和槽
        QString s;
        connect(&serialThread_1, &QThread::finished, ser, &QObject::deleteLater);           // 线程结束,自动删除对象
        connect(&serial_1, &QSerialPort::readyRead, ser, &SerialWorker::doDataReciveWork); // 主线程通知子线程接收数据的信号
        connect(ser, &SerialWorker::sendResultToGui, this, &MainWindow::handleResults);    // 主线程收到数据结果的信号
      //  connect(ser,SIGNAL(sendResultToGui(QString)), this, SLOT(handleResults(QString)));     //主线程收到数据结果的信号写法2
    
        // 3.开始运行子线程
        serialThread_1.start();                   // 线程开始运行
    }
    
    MainWindow::~MainWindow()
    {
        serialThread_1.quit();
        serialThread_1.wait();
        delete ui;
    }
    
    void MainWindow::InitSerialPortName()
    {
        // 清空下拉框
        ui->box_portName->clear();
    
        //通过QSerialPortInfo查找可用串口
        foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
        {
            QString showName = info.portName();
            qDebug() << showName+info.description();
            ui->box_portName->addItem(showName);
        }
        //波特率
            QStringList baudrateList;
            baudrateList<<"4800"<<"9600"<<"19200"<<"38400"<<"57600"<<"115200";
            ui->box_baudrate->addItems(baudrateList);//添加下拉列表选项
            ui->box_baudrate->setCurrentText("115200");//界面中初始值
        //    ui->box_baudrate->setView(new QListView(this));//该设置是配合qss的,不然item行高设置没效果
        //数据位
            QStringList databitList;
            databitList<<"5"<<"6"<<"7"<<"8";
            ui->box_dataBits->addItems(databitList);
            ui->box_dataBits->setCurrentText("8");
    //      ui->box_dataBits->setView(new QListView(this));
            //校验位
            QStringList parityList;
            parityList<<"无"<<"奇"<<"偶";
            ui->box_parityBit->addItems(parityList);
            ui->box_parityBit->setCurrentText("No");
    //      ui->box_parityBit->setView(new QListView(this));
            //停止位
            QStringList stopbitList;
            stopbitList<<"1"<<"2";
            ui->box_stopBit->addItems(stopbitList);
            ui->box_stopBit->setCurrentText("1");
    //      ui->box_stopBit->setView(new QListView(this));
            //流控制
    //        QStringList flowctrlList;
    //        flowctrlList<<"No"<<"Hardware"<<"Software";
    //        ui->boxFlowControl->addItems(flowctrlList);
    //        ui->boxFlowControl->setCurrentText("No");
          ui->boxFlowControl->setView(new QListView(this));
    }
    
    void MainWindow::on_btn_openPort_clicked()
    {
        if(ui->btn_openPort->text()==QString("打开串口"))
        {
            //设置串口名
            QString portName = (ui->box_portName->currentText()).split(":").at(0);
            qDebug() <<"当前打开串口为:"<<portName;
            serial_1.setPortName(portName);
    
            //设置波特率
            serial_1.setBaudRate(ui->box_baudrate->currentText().toInt());
    
            //设置停止位
            if(ui->box_stopBit->currentText() == "1")
                serial_1.setStopBits(QSerialPort::OneStop);
            else if(ui->box_stopBit->currentText() == "2")
                serial_1.setStopBits(QSerialPort::TwoStop);
    
            //设置数据位数
            if(ui->box_dataBits->currentText() == "8")
                serial_1.setDataBits(QSerialPort::Data8);
            else if(ui->box_dataBits->currentText() == "7")
                serial_1.setDataBits(QSerialPort::Data7);
            else if(ui->box_dataBits->currentText() == "6")
                serial_1.setDataBits(QSerialPort::Data6);
            else if(ui->box_dataBits->currentText() == "5")
                serial_1.setDataBits(QSerialPort::Data5);
    
            //设置奇偶校验
            if(ui->box_parityBit->currentText() == "无")
                serial_1.setParity(QSerialPort::NoParity);
            else if(ui->box_parityBit->currentText() == "偶")
                serial_1.setParity(QSerialPort::EvenParity);
            else if(ui->box_parityBit->currentText() == "奇")
                serial_1.setParity(QSerialPort::OddParity);
    
    //        //设置流控制
    //        serial_1.setFlowControl(QSerialPort::NoFlowControl);
    
            //打开串口
            if(!serial_1.open(QIODevice::ReadWrite))
            {
                QMessageBox::about(NULL, "提示", "无法打开串口!");
                return;
            }
    
            //下拉菜单控件失能
            ui->box_portName->setEnabled(false);
            ui->box_baudrate->setEnabled(false);
            ui->box_dataBits->setEnabled(false);
            ui->box_parityBit->setEnabled(false);
            ui->box_stopBit->setEnabled(false);
    
            ui->btn_openPort->setText(QString("关闭串口"));
    
        }
        else
        {
            //关闭串口
            serial_1.close();
            //下拉菜单控件使能
            ui->box_portName->setEnabled(true);
            ui->box_baudrate->setEnabled(true);
            ui->box_dataBits->setEnabled(true);
            ui->box_parityBit->setEnabled(true);
            ui->box_stopBit->setEnabled(true);
            ui->btn_openPort->setText(QString("打开串口"));
        }
    }
    
    void MainWindow::on_btn_clearText_clicked()
    {
        ui->browser_dataReceive->clear();
    }
    
    void MainWindow::handleResults(const QString &result)
    {
        qDebug() <<  "主线程收到结果数据:" << result << "线程ID:" << QThread::currentThreadId();
        //从界面中读取以前收到的数据
        QString oldString = ui->browser_dataReceive->toPlainText()+'\n';
        oldString = oldString + QString(result);
        //清空以前的显示
        ui->browser_dataReceive->clear();
        //重新显示
        ui->browser_dataReceive->append(oldString);
    }
    

    (5)serialworker.cpp文件

    #include "serialworker.h"
    
    SerialWorker::SerialWorker(QSerialPort *ser, QObject *parent) : QObject(parent),serial(ser)
    {
    
    }
    QString SerialWorker::ByteArrayToHexString(QByteArray data)
    {
        QString ret(data.toHex().toUpper());
        int len = ret.length()/2;
        qDebug()<<"收到字节长度为:"<<len;
        for(int i=1;i<len;i++)
        {
            ret.insert(2*i+i-1," ");
        }
        return ret;
    }
    
    void SerialWorker::doDataReciveWork()
    {    
        QByteArray buffer = serial->readAll();
        // 2.进行数据处理
        QString result = ByteArrayToHexString(buffer);
        qDebug() <<  "子线程收到数据:" << result << "线程ID:" << QThread::currentThreadId();
        // 3.将结果发送到主线程
        emit sendResultToGui(result);
    }
    
    
    展开全文
  • 4、QTableWidget控件显示多有连接的客户端的信息; 5、连接进来的客户端可以同时传输文件,互补影响; 6、客户端断开连接,QTableWidget中的客户端信息删除; 7、服务端可以显示传输进度、传输状态、传输文件名;...

    1、客户端链接:https://zhangzc.blog.csdn.net/article/details/122073564

    2、服务端界面如下图:

    3、当有一个客户端连接进来,开启一个线程对其进行管理;

    4、QTableWidget控件显示多有连接的客户端的信息;

    5、连接进来的客户端可以同时传输文件,互补影响;

    6、客户端断开连接,QTableWidget中的客户端信息删除;

    7、服务端可以显示传输进度、传输状态、传输文件名;

    8、文章后面给出服务端源码下载地址;

    9、主要代码:

    QThread* th = ThreadHandle::getClass().getThread();
        zzcSocket* tcpTemp = new zzcSocket(socketDescriptor);
    
        //获取对方的ip和端口
      
    展开全文
  • } } } 5、数据接收 /// /// 后台线程接收数据 /// /// private void ReceiveClient(object obj) { Socket _ClientSocket = (Socket)obj; while (true) { try { //获取数据长度 int receiveLength ...

    1、引入依赖库,无需第三方。

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    

    2、变量声明

           /// <summary>
            /// 缓冲器
            /// </summary>
    private byte[] result = new byte[1024];
            /// <summary>
            /// 最大连接数
            /// </summary>
    private int maxClientCount;
            /// <summary>
            /// 服务IP地址
            /// </summary>
    private string ip;
            /// <summary>
            /// 服务端口号
            /// </summary>
    private int port;
            // 编码
            // private string code;
            /// <summary>
            /// 客户端列表
            /// </summary>
    private List<Socket> ClientSockets;
            /// <summary>
            /// IP终端
            /// </summary>
    private IPEndPoint ipEndPoint;
            /// <summary>
            /// 服务端Socket 
            /// </summary>
    private Socket ServerSocket;
            /// <summary>
            /// 当前客户端Socket 
            /// </summary>
    private Socket ClientSocket;
    

    3、开启TCP服务

    ip = IPAddress.Any.ToString(); //服务于任意IP地址      
    port=8640;//服务端口,理论自定义范围 1-65535,不可与以开放端口冲突
    maxClientCount = 256; //设定最大连接数
    ClientSockets = new List<Socket>();
    ipEndPoint = new IPEndPoint(IPAddress.Any, port);      //初始化IP终端 
    ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);        //初始化服务端Socket 
    ServerSocket.Bind(this.ipEndPoint);      //端口绑定
    ServerSocket.Listen(maxClientCount);     //设置监听数目 
    Thread ServerThread = new Thread(() =>
    {
         ListenClientConnect();         //开启监听,后台线程,非阻塞
    })
    {
         IsBackground = true,
    };
    ServerThread.Start();//服务端线程开启 
    

    4、TCP连接侦听

    /// <summary>
    /// 后台线程侦听连接
    /// </summary>
    private void ListenClientConnect()
    {
         //设置循环标志位 
    	while (true)
    	{
    		try
    		{
    			//获取连接到服务端的客户端 
                ClientSocket = ServerSocket.Accept();
    			//将获取到的客户端添加到客户端列表 
    			ClientSockets.Add(ClientSocket);
    			//显示连接者信息
    			//Show_msg($@"客户端接入:{ClientSocket.RemoteEndPoint}");
    			//创建客户端消息线程,实现客户端消息的循环监听 
                Thread ReveiveThread = new Thread(() =>
    		    {
    				ReceiveClient(ClientSocket); //数据接收
                })
                {
                    IsBackground = true,
                };
                ReveiveThread.Start();
             }
             catch (Exception ex)
             {
                //Show_msg($@"连接侦听异常:{ex.Message}");
    		 }
    	}
    }
    

    5、数据接收

    /// <summary>
    /// 后台线程接收数据
    /// </summary>
    /// <param name="obj"></param>
    private void ReceiveClient(object obj)
    {
    	Socket _ClientSocket = (Socket)obj;
    	while (true)
    	{
    		try
    		{
    			//获取数据长度 
    			int receiveLength = _ClientSocket.Receive(result);
    			//获取客户端发来的数据 
    			string strData = Encoding.UTF8.GetString(result, 0, receiveLength);
                //Show_msg($@"客户端{_ClientSocket.RemoteEndPoint}】  发来数据:{strData}"); 
                /*
                	对接收到的数据进行处理
                */
                //向客户端回发数据
    			//_ClientSocket.Send(Encoding.UTF8.GetBytes($@"我已收到您发来的数据{strData }"));
    		}
    		catch (Exception e)//通讯出现异常 
    		{
    			//从客户端列表中移除该客户端 
    			this.ClientSockets.Remove(_ClientSocket);
                //断开连接 
    			//Show_msg($@"客户端{_ClientSocket.RemoteEndPoint}从服务器断开,断开原因:{e.Message}");
    			_ClientSocket.Shutdown(SocketShutdown.Both);
    			_ClientSocket.Close();
    			break;
    		}
    	}
    }
    
    展开全文
  • 使用C++编写的基于MFC和UDP通信协议的多线程程序,接收信息的功能单独在一个线程里,避免主界面卡顿,可以在循环接收信息,将信息显示在文本框并写入txt的同时,点击按钮发送输入另一个文本框的信息
  • c#编写串口通讯代码 多线程实现

    热门讨论 2015-12-31 12:55:00
    c#编写串口通讯代码 多线程实现 对串口通信测试具有极大的参考价值
  • email接收电子邮件,可针对多用户邮箱进行多线程下载电子邮件.zip
  • python使用pyqt多线程显示视频

    千次阅读 2020-04-14 16:05:27
    在正式开始之前,得说几句感想,在...在这个项目中,我使用了多线程来在界面上显示视频,今天想了想,还是写上这个,用于以后自己看或者给其他有兴趣的朋友看。 使用的技术:python + pyqt + opencv 在使用pyqt的...
  • 通过HTTP多线程并发post/get数据

    热门讨论 2013-09-27 11:35:30
    编译工具:VC++6.0 通过http进行多线程并发post/get数据从服务器上,并将数据显示在界面上。
  • 考虑到安卓蓝牙的套接字API接口采用的是双式的传输和接收方式,因此,在设计的时候为了保证主线程界面不会出现卡死的状况,需要在设计的时候采用线程进行管理。同时,为了方便后续资源释放,本系统将蓝牙通信的...
  • ! udp多线程的有关问题

    千次阅读 2020-12-29 07:22:59
    udp多线程的问题我做了个udp接收的测试程序,刚开始能收到数据,收了几条数据之后就报个错:QSocketNotifier:Socketnotifierscannotbeenabledordisabledfromanotherthread然后程序就收不到数据了,但是程序没有崩溃...
  • 用QT写CAN分析软件3--多线程接收数据

    千次阅读 2021-03-29 18:38:30
    今天利用QT多线程接收CAN的数据 1、首先新建一个candatabase的类来表示CAN到 的每一个帧数据 #ifndef CANDATABASE_H #define CANDATABASE_H #include <QObject> #include <QDateTime> class ...
  • 实现一个多线程的网络时间服务器,介绍如何综合运用多线程技术编程。每当有客户请求到达是,服务器将启动一个新线程为它返回当前时间,服务完毕后这个线程将自动退出,同时,用户界面会显示当前已接收请求的次数。
  • Java多线程超详解

    万次阅读 多人点赞 2019-06-11 01:00:30
    随着计算机的配置越来越高,我们需要将进程进一步优化,细分为线程,充分提高图形化界面的多线程的开发。这就要求对线程的掌握很彻底。 那么话不多说,今天本帅将记录自己线程的学习。 线程的相关API //获取当前...
  • QT多线程-应对复杂数据处理、串口数据实时显示

    千次阅读 多人点赞 2019-07-31 16:55:41
    任何收发两端速度不一致的通讯,都需要在它们之间使用一个足够大的FIFO缓冲区。...◆多线程锁 ◆多线程日志 ◆日志文件占用的磁盘空间的可控性。 ◆日志中的时间包括毫秒 ◆传输的数据对应的每个字节到底的英文...
  • 使用多线程处理输入的数据

    千次阅读 2021-02-03 21:17:49
    TensorFlow 的 Session 对象是支持多线程的,因此多个线程可以很方便地在同一个会话下对同一个队列并行地执行操作。Python 本身也提供了创建线程的threading.py,这个文件提供了Thread 类来创建线程,Thread 类的 ...
  • 【Python 爬虫】多线程爬取

    千次阅读 2022-03-20 10:44:40
    文章目录前言一、多进程库(multiprocessing)二、多线程爬虫三、案例实操四、案例解析1、获取网页内容2、获取每一章链接3、获取每一章的正文并返回章节名和正文4、将每一章保存到本地5、多线程爬取文章 前言 简单...
  • 这里写自定义目录标题1. Qt 安装2. Pycharm 设置2.1 Pyqt5 和 pyinstaller 包2.2Pycharm pyqt工具配置3 PyQt5 图形界面设计4 Pyinstaller 打包成exe 1. Qt 安装 2. Pycharm 设置 你好! 这是你第一次使用 Markdown...
  • Qt练习:多线程串口通信

    千次阅读 2020-04-06 22:14:42
    最近在学习Qt编程,为了练手,想做一个串口通信的小软件为之后的项目做准备,经过几天的学习与练习初步搭建起了多线程串口通信的框架及较少的其他功能 功能简介 串口接收 主线程显示ui,子线程接收串口数据,数据...
  • C++多线程详细讲解

    万次阅读 多人点赞 2021-03-19 20:33:26
    C++多线程基础教程 目录 1 什么是C++多线程? 2 C++多线程基础知识 2.1 创建线程 2.2 互斥量使用 lock()与unlock(): lock_guard(): unique_lock: condition_variable: 2.3 异步线程 async与future: shared_future ...
  • Java多线程实现TCP网络Socket编程(C/S通信)

    万次阅读 多人点赞 2020-10-26 09:45:38
    本篇详细记录实现java多线程通信,目标达到客户端可以一次接收服务器发送的多条信息,避免阻塞。将客户端接收信息功能独立为一个线程来完成,进一步完善TCP的Socket网络通信,C/S软件架构的程序设计!
  • Linux下基于socket多线程并发通信的实现,论文,pdf文档
  • Qt网络通信,多线程实现UDP通信

    千次阅读 2020-07-28 21:17:12
    Qt使用多线程进行UDP通信 UDP 由于要使用套接字,所以需要在服务器和客户端的工程文件中都添加QT += core gui network 使用writeDatagram方法传输数据,readDatagram方法接收数据。QT在调用writeDatagram方法时候会...
  • 在QT网络编程中,服务器往往需要和多个客户端保持连接,因此,我在熟悉多线程编程过程中,在TCP服务每接收到一个客户端连接请求,就新建一个线程。客户端也是在新建的线程中维护的。 程序的思路如下: 程序使用了非...
  • MFC多线程各种线程用法

    万次阅读 多人点赞 2018-06-25 15:15:41
    一、问题的提出 编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为 IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,...
  • Java多线程实现多用户与服务端Socket通信

    千次阅读 多人点赞 2020-11-02 13:54:36
    Java多线程实现多用户与服务端Socket通信,类似QQ、微信、视频等客户端,多用户与服务器通信。详细记录服务端多线程的实现,目标是多用户(客户端)能够同时与服务器建立连接并通信,避免阻塞,进一步完善TCP的...
  • 线程概述 线程的创建 1. 继承Thread类 2. 实现Runnable接口 3. 实现Callable接口 4. 使用线程池 线程的调度 线程的生命周期 线程同步 1. 方法一:同步代码块 2. 方法二:同步方法 3. 方法三:Lock(锁): 4. 对比三种...
  • C语言实现基于TCP的多线程聊天室

    千次阅读 多人点赞 2020-01-04 15:16:24
    基于TCP的服务器/客户机的模型 ...服务器的思路是等待客户端的连接,并且实时接收每个连接上来了的客户端发送的消息,并将这个消息包打包发送给其他客户端。 1.创建套接字 int sfd = socket(AF_INET,SOC...
  • Java多线程游戏仿真实例分享

    万次阅读 多人点赞 2021-02-02 18:20:57
    多线程的创建、多线程的应用、多线程的特点以及多线程的注意事项) 2、如何让小球在画面中真实地动起来?(赋予小球匀速直线、自由落体、上抛等向量运动) 3、多线程游戏仿真实例分享(飞机大战、接豆人、双线挑战...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 196,627
精华内容 78,650
关键字:

多线程接收显示