QT下TCP协议实现数据网络传输

2023-05-16

QT开发框架以其跨平台的优势,在全世界IT界如雷贯耳。其封装了功能齐全的各种类,大大的提高了开发者的效率。本篇内容将介绍如何使用QT 6.4.1框架开发服务器和客户端程序,让两端能够首发消息,服务端往客户端发送文件(客户端往服务器发送类似,没有实现)。

1.运行效果

 说明:首先运行同时运行客户端和服务端程序,服务绑定端口开启服务,客户端连接服务器。然后服务器和客户端互相打招呼,然后服务器给客户端发送一首唐诗。

2.关键代码:

2.1服务端代码

2.1.1 服务端主函数

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

2.1.2 QTcpServer实现类

头文件和实现:

#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H

#include <QObject>
#include <QTcpServer>

class MyTcpServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit MyTcpServer(QObject *parent = nullptr);
    //该函数是由框架调用
    void incomingConnection(qintptr socketDescriptor);

signals:
    void newClient(qintptr socket);

};

#endif // MYTCPSERVER_H
#include "mytcpserver.h"

MyTcpServer::MyTcpServer(QObject *parent)
    : QTcpServer{parent}
{

}

//该函数是由框架调用
void MyTcpServer::incomingConnection(qintptr socketDescriptor)
{
    emit newClient(socketDescriptor);
}

2.1.3 主窗口类

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "MyTcpServer.h"
#include <QLabel>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

signals:
    void start(QString file);
    void sendMsg(QByteArray msg);

private slots:
    void on_start_clicked();

    void on_selectFile_clicked();

    void on_sendMsg_clicked();

    void on_transferFile_clicked();

private:
    Ui::MainWindow *ui;
    MyTcpServer *m_server;
    QLabel *m_status;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QMessageBox>
#include <QRandomGenerator>
#include <qDebug>
#include <QFileDialog>
#include <QString>
#include "sendfile.h"

//alt +回车添加自动添加头文件
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->lineEditPort->setText("9521");
    ui->lineFile->setText("C:\\Users\\Administrator\\Desktop\\OKR设定.txt");
    ui->progressBar->setRange(0, 100);
    ui->progressBar->setValue(0);

    //创建服务器socket
    m_server = new MyTcpServer(this);
    connect(m_server, &MyTcpServer::newClient, this, [=](qintptr socket) {
        ui->textEditContent->append("检测到有新的客户端连接");
        //有新连接
        m_status->setPixmap(QPixmap(":/ok.png").scaled(20, 20));
        QThread *subThread = new QThread;
        SendFile* worker = new SendFile(socket);
        worker->moveToThread(subThread);

        //子线程工作是需要主线程给其发信号通知工作,此处用来通知子线程给客户端发送文件
        connect(this, &MainWindow::start, worker, &SendFile::working);

        connect(worker, &SendFile::done, this, [=](){
            ui->textEditContent->append("检测到客户端退出");
            //客户端断开
            m_status->setPixmap(QPixmap(":/error.png").scaled(20, 20));
            qDebug() << "销毁子线程资源";
            subThread->quit(); //通知退出
            subThread->wait(); //等任务做完
            subThread->deleteLater(); //相当于对new的对象进行delete操作
            worker->deleteLater();
        });
        //不能在子线程操作ui对象,读和写都不行,需要子线程通过信号通知ui线程间接操作ui对象
        connect(worker, &SendFile::text, this, [=](QByteArray msg){
            QVector<QColor> colors = {
                Qt::red, Qt::green, Qt::black, Qt::blue,
                Qt::darkRed, Qt::cyan, Qt::magenta
            };
            int index = QRandomGenerator::global()->bounded(colors.size());
            ui->textEditContent->setTextColor(colors.at(index));
            ui->textEditContent->append(msg);
        });
        //显示客户端发来的消息
        connect(worker, &SendFile::showRecvMsg, this, [=](QByteArray msg){
            ui->textEditContent->append("收到消息:" + msg);
        });

        //通知子线程发送一行文本
        connect(this, &MainWindow::sendMsg, worker, &SendFile::sendMsg);

        connect(worker, &SendFile::updateProgressBar, this, [=](int value){
            ui->progressBar->setValue(value);
        });

        subThread->start();
      });

    //处理状态栏,new一个QLabel,可以制定父对象,也可以不指定,因为需要把
    //它设置到状态栏中,设置后其父对象默认就是状态栏,状态栏析构后就会回收QLabel
    //不用delete
    m_status = new QLabel;
    m_status->setPixmap(QPixmap(":/error.png").scaled(20, 20));
    ui->statusbar->addWidget(new QLabel("状态:"));
    ui->statusbar->addWidget(m_status);
}

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


void MainWindow::on_start_clicked()
{
    unsigned short port = ui->lineEditPort->text().toUShort();
    //绑定端口等待客户端连接,有客户端连接触发信号:[signal] void QTcpServer::newConnection()
    //QT中用于通信的QTcpSocket套接字对象不能跨线程访问
    m_server->listen(QHostAddress::Any, port);
    ui->start->setDisabled(true);
}


void MainWindow::on_selectFile_clicked()
{
    QString file = QFileDialog::getOpenFileName(this);
    if (!file.isEmpty()) {
        ui->lineFile->setText(file);
    }
}


void MainWindow::on_sendMsg_clicked()
{
   QString msg = ui->lineEditMsg->text();//.toUShort();
   emit sendMsg(msg.toUtf8());
   ui->textEditContent->append("发出消息:" + msg);
}

void MainWindow::on_transferFile_clicked()
{
    if (ui->lineFile->text().isEmpty()) {
        QMessageBox::information(this, "提示", "请选择要发送的文件");
        return;
    }
    emit start(ui->lineFile->text());
}

2.1.4 网络处理线程类

#ifndef SENDFILE_H
#define SENDFILE_H

#include <QObject>
#include <QString>
#include <QTcpSocket>
#include <QtEndian>

class SendFile : public QObject
{
    Q_OBJECT
public:
    explicit SendFile(qintptr socket, QObject *parent = nullptr);
    void working(QString file);
    void sendMsg(QByteArray msg);

signals:
    void done();
    void text(QByteArray msg);
    void showRecvMsg(QByteArray msg);
    void updateProgressBar(int value);

private:
    qintptr m_socket;
    QTcpSocket* m_tcpConn;
};

#endif // SENDFILE_H
#include "sendfile.h"
#include <QThread>
#include <QFile>
#include <qDebug>
#include <QTextCodec>

SendFile::SendFile(qintptr socket, QObject *parent)
    : QObject{parent}
{
    //传递过来了用于通信的套接字,就可以和对端通信了
    m_socket = socket;
}

void SendFile::working(QString file) {
    qDebug() << "子线程ID: " << QThread::currentThread();
    //注意:m_tcpConn的创建要在子线程中
    m_tcpConn = new QTcpSocket;
    //用文件描述符初始化m_tcpConn
    m_tcpConn->setSocketDescriptor(m_socket);

    //检测客户端断开
    connect(m_tcpConn, &QTcpSocket::disconnected, this, [=]() {
        m_tcpConn->close();
        m_tcpConn->deleteLater();
        emit done();
        qDebug() << "检测到客户端退出,我的资源也进行了销毁,再见!";
    });

    //检测客户端发来数据
    connect(m_tcpConn, &QTcpSocket::readyRead, this, [=]() {
        //接收数据并把数据发送给主线程进行显示
        QByteArray data = m_tcpConn->readAll();
        emit showRecvMsg(data);
    });

    qDebug() << "传输的文件: " << file;
    QFile opFile(file);
    bool ret = opFile.open(QFile::ReadOnly);
    if (ret) {
        emit updateProgressBar(0);
        //此处打开的是windows下的文件,windows默认是GBK编码,所以此处指定编码GBK
        QTextCodec *codec = QTextCodec::codecForName("GBK");
        qint64 fileSize = opFile.size();
        qint64 sendSize = 0;
        while (!opFile.atEnd()) {
            //自定格式发包,将发送长度转换成大端存储发送到对端
            QByteArray line = opFile.readLine();
            sendSize += line.size();
            QString strUnicode = codec->toUnicode(line);
            QByteArray utf8line = strUnicode.toUtf8();
            //以下代码写成两行比较稳定,如果写成
            //uint32_t len = qToBigEndian(utf8line.size());在某些环境转换长度就为0
            uint32_t orgLen = utf8line.size();
            uint32_t len = qToBigEndian(orgLen);
            QByteArray data((char*)&len, 4);
            data.append(utf8line);
            //发送一行数据给对端
            m_tcpConn->write(data);
            emit text(utf8line);
            emit updateProgressBar(100 * sendSize / fileSize);
            //为了减轻对端压力,休眠一会
            QThread::sleep(1);
        }
    }
    opFile.close();
}

void SendFile::sendMsg(QByteArray msg) {
    //用文件描述符初始化m_tcpConn
    m_tcpConn = new QTcpSocket;
    m_tcpConn->setSocketDescriptor(m_socket);

    //检测客户端断开
    connect(m_tcpConn, &QTcpSocket::disconnected, this, [=]() {
        m_tcpConn->close();
        m_tcpConn->deleteLater();
        emit done();
    });

    //检测客户端发来数据
    connect(m_tcpConn, &QTcpSocket::readyRead, this, [=]() {
        //接收数据并把数据发送给主线程进行显示
        QByteArray data = m_tcpConn->readAll();
        emit showRecvMsg(data);
    });

    //QT默认是UTF8编码,所以输入框是UTF8编码,此处指定编码方式为UTF8
    QTextCodec *codec = QTextCodec::codecForName("UTF8");
    QString strUnicode = codec->toUnicode(msg);
    QByteArray utf8line = strUnicode.toUtf8();
    uint32_t orgLen = utf8line.size();
    uint32_t len = qToBigEndian(orgLen);
    //拼接头:表示长度
    QByteArray data((char*)&len, 4);
    //拼接发送内容
    data.append(utf8line);
    m_tcpConn->write(data);
}

2.1.5 pro工程文件

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat
CONFIG += c++17 console

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp \
    mytcpserver.cpp \
    sendfile.cpp

HEADERS += \
    mainwindow.h \
    mytcpserver.h \
    sendfile.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

RESOURCES += \
    res.qrc

2.2客户端代码

2.2.1 主函数

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

2.2.2 主窗口类

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

signals:
    void startConnect(QString, unsigned short);
    void disConnect();
    void sendMsg(QByteArray msg);

private slots:
    void on_connServer_clicked();

    void on_sendMsg_clicked();

    void on_disconnServer_clicked();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QMessageBox>
#include <QRandomGenerator>
#include "recvfile.h"

//多线程中,主线程负责相应ui事件,创建子线程,子线程处理服务端发过来的数据
//QT中通信的套接字是不能跨线程访问的,所以客户端中用于通信的套接字是不能在
//主线程创建的,需要在子线程创建通讯套接字,主线程把ip和端口传输给子线程
//子线程new一个QTcpSocket的对象,然后子线程用这个通讯套接字接受服务端
//发过来的数据
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->IP->setText("127.0.0.1");
    ui->port->setText("9521");
    ui->disconnServer->setDisabled(true);
    //创建子线程
    QThread *subThread = new QThread;
    //重点说明:此处new RecvFile时候不能给其指定父对象
    //否则worker移动到子线程就会不生效,谨记谨记!!!
    RecvFile* worker = new RecvFile;
    worker->moveToThread(subThread);
    connect(this, &MainWindow::startConnect, worker, &RecvFile::connectServer);
    //连接服务端成功
    connect(worker, &RecvFile::connectOk, this, [=]() {
        //QMessageBox::information(this, "提示", "成功连接了服务器");
        ui->content->append("成功连接了服务器");
        ui->disconnServer->setDisabled(false);
        ui->connServer->setDisabled(true);
    });
    connect(worker, &RecvFile::message, this, [=](QByteArray msg) {
        QVector<QColor> colors = {
            Qt::red, Qt::green, Qt::black, Qt::blue,
            Qt::darkRed, Qt::cyan, Qt::magenta
        };
        int index = QRandomGenerator::global()->bounded(colors.size());
        ui->content->setTextColor(colors.at(index));
        ui->content->append("收到消息:" + msg);
    });
    connect(worker, &RecvFile::gameOver, this, [=]() {
        qDebug() << "主线程销毁子线程";
        subThread->quit();
        subThread->wait();
        subThread->deleteLater();
        worker->deleteLater();
    });
    connect(worker, &RecvFile::disconnected, this, [=] {
        ui->content->append("与服务器断开了连接");
        ui->disconnServer->setDisabled(true);
        ui->connServer->setDisabled(false);
    });
    //断开服务器连接
    connect(this, &MainWindow::disConnect, worker, &RecvFile::disConnect);
    //给服务器发消息
    connect(this, &MainWindow::sendMsg, worker, &RecvFile::sendMsg);
    //start之后,线程仍然不能正常工作,仍然需要信号触发
    subThread->start();
    qDebug() << "主线程id:" << QThread::currentThread();
}

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


void MainWindow::on_connServer_clicked()
{
    QString ip = ui->IP->text();
    unsigned short port = ui->port->text().toUShort();
    emit startConnect(ip, port);
}

void MainWindow::on_sendMsg_clicked()
{
    QString msg = ui->msg->text();
    emit sendMsg(msg.toUtf8());
    ui->content->append("发出消息:" + msg);
}

void MainWindow::on_disconnServer_clicked()
{
    emit disConnect();
    ui->disconnServer->setDisabled(true);
    ui->connServer->setDisabled(false);
}

2.2.3 处理网络数据的子线程类

#ifndef RECVFILE_H
#define RECVFILE_H

#include <QByteArray>
#include <QObject>
#include <QTcpSocket>

class RecvFile : public QObject
{
    Q_OBJECT
public:
    explicit RecvFile(QObject *parent = nullptr);
    void connectServer(QString ip, unsigned short port);
    void dealData();
    void disConnect();
    void sendMsg(QByteArray msg);

signals:
    void connectOk();
    void message(QByteArray msg);
    void gameOver();
    void disconnected();

private:
    QTcpSocket *m_tcpScoket;
};

#endif // RECVFILE_H
#include "recvfile.h"
#include <QThread>
#include <QtEndian>

RecvFile::RecvFile(QObject *parent)
    : QObject{parent}
{

}

void RecvFile::connectServer(QString ip, unsigned short port) {
    qDebug() << "子线程ID:" << QThread::currentThread();
    m_tcpScoket = new QTcpSocket;
    //该函数是非阻塞函数,所有需要connect来注册回调,告诉我连接ok
    m_tcpScoket->connectToHost(QHostAddress(ip), port);
    connect(m_tcpScoket, &QTcpSocket::connected, this, &RecvFile::connectOk);
    //连接之后怎么怎么知道有数据到来呢,继续connect连接来通知我,槽使用匿名槽函数
    connect(m_tcpScoket, &QTcpSocket::readyRead, this, [=](){
        //QByteArray all = m_tcpScoket->readAll();
        //emit message(all);
        dealData();
        //emit gameOver();
    });
    connect(m_tcpScoket, &QTcpSocket::disconnected, this, &RecvFile::disconnected);
}

void RecvFile::dealData() {
    unsigned int totalBytes = 0;
    unsigned int recvBytes = 0;
    QByteArray block;

    if (0 == m_tcpScoket->bytesAvailable()) {
        qDebug() << "没有数据";
        return;
    }
    if (m_tcpScoket->bytesAvailable() >= sizeof(int)) {
        QByteArray head = m_tcpScoket->read(sizeof(int));
        //网络字节序转小端
        totalBytes = qFromBigEndian(*(int*)head.data());
        qDebug() << "接收数据长度::" << totalBytes;
    }
    else {
        return;
    }
    while (totalBytes -recvBytes > 0 && m_tcpScoket->bytesAvailable()) {
        block.append(m_tcpScoket->read(totalBytes - recvBytes));
        recvBytes = block.size();
    }
    if (totalBytes == recvBytes) {
        emit message(block);
    }
    //如果还有数据继续读取
    if (m_tcpScoket->bytesAvailable() > 0) {
        dealData();
        qDebug() << "递归调用数据接收";
    }
}

void RecvFile::disConnect() {
    //关闭连接,销毁自己
    m_tcpScoket->close();
    //m_tcpScoket->deleteLater();
}

//给服务器发消息
void RecvFile::sendMsg(QByteArray msg) {
    m_tcpScoket->write(msg);
}

3.开发注意事项

(1)不能在子线程直接操作ui对象,而是通过发送信号给主线程间接操作ui对象

(2)QT处理大端和小端字节序的问题,提供了如下两组四个函数:

  组一(工作于小端机器):  qToBigEndian  (小端转大端)  qFromBigEndian (大端转小端)
  组二(工作于大端机器): qToLittleEndian  (大端转小端)  qFromLittleEndian (小端转大端)

其中组一用在小端机器上,组二用在大端机,简单记忆后缀是BigEndian工作在小段机器,后缀是LittleEndian工作在大端机器,工作机器刚好和后缀相反。

(3)QT有父子对象树机制来回收内存,父对象析构时会先析构子对象。

(4)多线程中,主线程负责相应ui事件,创建子线程,子线程处理服务端发过来的数据QT中通信的套接字是不能跨线程访问的,所以客户端中用于通信的套接字是不能在主线程创建的,需要在子线程创建通讯套接字,主线程把ip和端口传输给子线程子线程new一个QTcpSocket的对象,然后子线程用这个通讯套接字接受服务端发过来的数据

最后附上源码下载地址: https://download.csdn.net/download/hsy12342611/87178417

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT下TCP协议实现数据网络传输 的相关文章

  • STM32中断NVIC的概念及中断编程步骤

    文章目录 前言一 NVIC 简介1 NVIC 寄存器简介2 NVIC 中断配置固件库 二 优先级的定义1 优先级定义2 优先级分组 三 中断编程步骤1 使能外设某个中断2 初始化 NVIC InitTypeDef 结构体3 编写中断服务函数
  • 【论文阅读笔记】基于RGBD相机的四旋翼多小快速运动目标感知与避障

    文章名称 xff1a Perception and Avoidance of Multiple Small Fast Moving Objects for Quadrotors with Only Low cost RGBD Camera
  • vscode配置C++调试

    vscode打开一个目录后生成 vscode目录 xff0c 如果配置有问题 xff0c 可以把 vscode删掉 调试首先点击左侧按钮进入run and debug xff0c 这里面默认是什么都没有的 xff0c 点击选择C 43 43
  • Java利用技巧——通过JNI加载dll

    0x00 前言 Java可以通过JNI接口访问本地的动态连接库 xff0c 从而扩展Java的功能 本文将以Tomcat环境为例 xff0c 介绍通过jsp加载dll的方法 xff0c 开源代码 xff0c 记录细节 0x01 简介 本文将
  • LeetCode-两数之和

    给定一个整数数组 nums 和一个整数目标值 target xff0c 请你在该数组中找出 和为目标值 target 的那 两个 整数 xff0c 并返回它们的数组下标 你可以假设每种输入只会对应一个答案 但是 xff0c 数组中同一个元素
  • LeetCode-子数组的最小值之和

    给定一个整数数组 arr xff0c 找到 min b 的总和 xff0c 其中 b 的范围为 arr 的每个 xff08 连续 xff09 子数组 由于答案可能很大 xff0c 因此 返回答案模 10 9 43 7 实例1 输入 xff1
  • LeetCode-只出现一次的数字

    给定一个非空整数数组 xff0c 除了某个元素只出现一次以外 xff0c 其余每个元素均出现两次 找出那个只出现了一次的元素 说明 xff1a 你的算法应该具有线性时间复杂度 你可以不使用额外空间来实现吗 xff1f 输入 2 2 1 输出
  • 关于结构体成员变量用 . 还是 ->

    之前一直认为引用结构体成员 xff0c 指针的话用 gt xff0c 成员变量的话用 但是一直都没去深究过 xff0c 今天遇到一个复杂的 xff0c 决心去了解一下 typedef struct IPC ISP CFG DATA IPC
  • 顺序表的建立 基本输入输出

    输入数据的个数n 输入n个数 然后输出 input 5 1 2 3 4 5 output 1 2 3 4 5 以下是代码 xff1a include lt stdio h gt include lt stdlib h gt define l
  • 离散题目18--求传递闭包

    离散题目18 Time Limit 1000MS Memory Limit 65536KB Submit Statistic Problem Description 给出一个集合A和A上的关系R xff0c 求关系R的传递闭包 例如 xff
  • 基于MSP430红外循迹小车

    2021 个人公众号 高瞻猿瞩 xff0c 会在其中发布一些有趣或是实用的编程内容 xff0c 大部分都是些轻松加愉快的内容 xff0c 欢迎大家前来看看 xff01 可在公众号恢复关键词 430 51 树莓派 循迹小车测试视频 可以获取相
  • 基于51单片机的简单方波发生器

    一个按键可以调整频率的简易方波信号发生器 xff0c 当频率超出范围时LED亮 xff0c 频率范围是100 1000hz include lt reg52 h gt sbit PWMOUT 61 P1 0 sbit LED1 61 P2
  • matlab绘制垂线(x轴或y轴)

    使用line函数就可以绘制垂线 1 绘制垂直于x轴的垂线 line xvalue xvalue y1 y2 xff1b 比如绘制x 61 5 y取值为 0 10 xff1b line 5 5 0 10 2 绘制垂直于y轴的垂线 line x
  • ubuntu解决中文乱码

    1 查看当前系统使用的字符编码 locale LANG 61 en US LANGUAGE 61 en US LC CTYPE 61 34 en US 34 LC NUMERIC 61 34 en US 34 LC TIME 61 34 e
  • ROS 在工作空间中创建python程序

    ROS 在工作空间中创建python程序 基于ros xff0c 在工作空间catkin ws中创建pkg和python程序 xff0c 并进行编译使其可以用rosrun进行运行 xff0c 参考 xff1a 参考 默认前面已经创建了cat
  • 关于AD15铺铜的注意事项

    1 在铺好信号线和电源线后再考虑是否在铺地之前先手动连接地线 因为在铺地时有一个间距问题 xff0c 如果有限地线的间距太小 xff0c 那么在铺地时就会不成功 xff0c 导致墨迹个地没有被接进去 还有就是要考虑敷铜时的间距 xff0c
  • AD15 建立铺铜间距规则

    系统默认的普通间距就是系统的clearance 10mil xff0c 可是默认普通出来的话间距太小了 xff0c 于是乎可以建立一个普通规则 xff0c 但是要注意你所建立的铺铜规则优先级永远在默认优先级之前 xff08 比如你的poly
  • AD15 修改铺铜(去除自己不想要的铺铜区域)

    1 点击place gt polygon pour cutout 2 出现光标 xff0c 然后把你想要去除的那个区域选中 xff0c 如图一所示 xff0c 单击右键退出选择模式 3 双击没有被选中的区域 xff0c 软件提示重新铺铜 x
  • 串口缓冲区管理分析

    一 概述 xff1a 串口使用时一般包含两个缓冲区 xff0c 即发送缓冲区和接收缓冲区 发送数据时 xff0c 先将数据存在发送缓冲区 xff0c 然后通过串口发送 xff1b 接收数据时 xff0c 先将接收的数据存在接收缓冲区 xff
  • JLINK给STM32下载的两种模式--jtag & sw连线及配置

    jtag线就不说了 xff0c 将jlink的Vref GND TMS TCK分别接至SW接口 对于STM32F103RCT6来说 xff1a TMS PA12 xff0c TCK PA14 关于KEIL MDK中的设置如下图所示就可以了

随机推荐

  • 3.3V过压保护电路

    好久没写了 xff0c 今天就写一些工作中用到的一个电路 3 3V过压保护电路 通常一个电路中给单片机等对电压信息敏感的器件供电时都会小心翼翼 xff0c 严防前级降压电路出问题 xff0c 我就碰到过12V转5V的1117奔溃记过加在ST
  • eagle使用注意点

    使用eagle也有快一年时间了 xff0c 刚开始很不习惯 xff0c 后来习惯了也还可以 xff0c 这里我举出几个设计中经常出错的地方 xff1a 1 PCB翻转问题 xff1a 在翻转PCB文件时一定要打开torigin borigi
  • 自制pixhawk电脑不识别com口

    在原版pix上面进行改版很方便 xff0c 可以去除很多不必要的电路 笔者将电源管理芯片去除 xff0c 5V来源于变压器输出或者是连接电脑时的USB供电 xff0c 并将它们并联起来 xff0c 但是板子做回来焊接后发现问题如下 xff1
  • eagle pcb v8.2 便捷性大大提升

    eagle pcb在被Autodesk收购之前是7 x版本 xff0c 但是却有一些一直被吐槽的东西 xff0c 说实话这些东西确实增加了布线难度 xff0c 增加了布板时间 xff1a 1 real time DRC xff1a 在7 x
  • Ubuntu firefox 显示在运行无法打开,如何在终端关闭进程

    用top命令找不到firfox的进程 xff0c 查看某个用户运行的进程 xff1a ps u username grep eclipse 查看用户名为 xff1a username 的用户是否运行了eclipse 查看用户当前运行fire
  • 【万字详解】cJSON解析

    目录 1 通过README文件 xff0c 初步了解cJSON xff1a 1 1 头文件的开头和结尾 xff1a 1 2 头文件关于cJSON类型的宏定义 1 3 头文件中的extern 2 阅读并且分析cJSON源码 2 1 结构体st
  • VINS-mono 解析 新特征

    在17 12 29 xff0c VINS更新了代码加入了新的特征 xff0c 包括map merge 地图合并 pose graph reuse 位姿图重利用 online temporal calibration function 在线时
  • VINS-mono 位姿图 重利用测试

    在前一篇博文里介绍了VINS mono pose graph reuse功能的使用 xff0c 这里接着贴出一些延伸的测试 xff0c 并进行一些探讨 延伸测试 一般来说 xff0c 加载地图是进行非GPS定位必要的一步 这里根据新的VIN
  • 2022年全国大学生电子设计大赛省赛A题

    2022年全国大学生电子设计大赛省赛A题 交流电子负载 文章目录 2022年全国大学生电子设计大赛省赛A题 交流电子负载 前言一 总体思路二 模块设计1 半桥模块2 测量模块3 辅助电源模块 三 主电路搭建总结 前言 2022年全国大学生电
  • linux下使用shell发送http请求

    一 curl 1 get请求 curl命令默认下就是使用get方式发送http请求 curl www baidu com 2 post请求 使用 d参数 xff0c 形式如下 xff1a curl d 34 param1 61 value1
  • 网络摄像头 接口协议 ONVIF,PSIA,CGI,ISAPI

    ONVIF致力于通过全球性的开放接口标准来推进网络视频在安防市场的应用 xff0c 这一接口标准将确保不同厂商生产的网络视频产品具有互通性 2008年11月 xff0c 论坛正式发布了ONVIF第一版规范 ONVIF核心规范1 0 随着视频
  • VLC架构及流程分析

    注明 xff1a 此文为转载 原文地址 xff1a https jiya io archives vlc learn 2 html 由于本人之前由于在工作中需要对VLC进行二次开发 因此进行了相关工作的开发 xff08 由于工作原因 目前暂
  • 学习、使用C++开发是不是过时了?

    C 43 43 在开发过程中真心很尴尬 1 拿相同薪水使用不同语言的程序员 xff0c 开发大多数相同的常见业务需求 xff0c C 43 43 总是进度较慢 xff08 不考虑时 空复杂性及效率 xff09 2 扩展性 跨平台 资源 内存
  • strcat()函数的用法

    这几天的一次程序练习中用到了strcat 函数 xff0c 但也想到了一些问题 我们都知道strcat str ptr 是将字符串ptr内容连接到字符串str后 xff0c 然后得到一个组合后的字符串str xff0c 比如 str字符串内
  • libQtCore.so.4 undefined symbol :g_main_context_push_thread_default

    开发板终端执行qt程序 qtDemo qws 报错 xff1a libQtCore so 4 undefined symbol g main context push thread default 解决方案 xff1a cd DVSDK p
  • curl时设置Expect的必要性

    curl 在项目中使用频率较高 xff0c 比如内部接口 第三方 api 图片存储服务等 xff0c 但是我们在使用 curl 时可能并没有注意到 Expect 这个请求头信息 xff0c 而 Expect 设置不正确 xff0c 会导致不
  • 奇偶校验原理

    奇校验 xff1a 求一个字节8位中 1 的个数 xff0c 添加一位校验位 xff0c 使9位中 1 的个数为奇数 xff1b 偶校验同理 奇校验就是让原有数据序列中 xff08 和要加上的一位 xff09 1的个数为奇数 如010001
  • CreateMutex函数函数用来实现进程互斥

    CreateMutex函数 正常情况下 xff0c 一个进程的运行一般是不会影响到其他正在运行的进程的 但是对于某些有特殊要求的如以独占方式使用串行口等硬件设备的程序就要求在其进程运行期间不允许其他试图使用此端口设备的程序运行的 xff0c
  • C++与QML交互总结

    一直对于QT的理解和使用都停留在主窗口程序和控制台程序 xff0c 虽然QT的新东西QML听过也接触过 xff0c 但是基本上没梳理过调用流程 趁着旧项目要使用QML技术 xff0c 现在就将C 43 43 和QML交互进行总结 目录 一
  • QT下TCP协议实现数据网络传输

    QT开发框架以其跨平台的优势 xff0c 在全世界IT界如雷贯耳 其封装了功能齐全的各种类 xff0c 大大的提高了开发者的效率 本篇内容将介绍如何使用QT 6 4 1框架开发服务器和客户端程序 xff0c 让两端能够首发消息 xff0c