嵌入式Linux应用程序开发-TCP-IP网络通信应用程序

2023-05-16

作为全世界最优秀的开源操作系统,Linux内部已经集成了强大的网络协议栈,并向应用层提供丰富的系统调用,开发者可以基于通用的系统调用接口,使用Linux内核提供的网络功能。
如果要分析Linux内部的网络通信机制以及实现原理,相信不是一时半刻或片文只字能描述清楚,一般的应用开发者可以通过网上搜索资料去了解一下,但在初学阶段,不建议去深入研究。
因此,本章节只是站在应用开发的角度,描述如何开发嵌入式QT的网络应用程序。
        TCP/IP协议模型(Transmission Control Protocol/Internet Protocol),包含了一系列构成互联网基础的网络协议,是Internet的核心协议。
它是一种面向连接的、可靠的、基于字节流的传输协议。关于TCP/IP协议的具体实现原理,本文不进行描述(关于TCP/IP的实现原理描述,其复杂度已经可以用一本书来具体阐述了)。
本文着重描述在嵌入式QT环境下,如何使用TCP/IP进行数据通信。
对于TCP/IP的客户端(TCP-Client)角色,在进行数据通信之前,一般会经历以下过程:
(1)调用socket套接字函数,创建套接字的文件描述符。
(2)配置连接参数(需要连接的服务器IP,端口,连接协议,等等)。
(3)基于套接字的文件描述符,调用connect函数,连接指定的服务器。
(4)处理connect过程中可能出现的情况。(如连接成功,连接出错,找不到服务器等)
(5)connect成功后,调用数据发送接口,进行数据发送。
(6)调用数据接收接口,并处理接收到的网络数据。(Linux C语言开发,可以阻塞接收或使用select/poll机制接收。QT开发,可以使用信号槽机制进行接收。)
        使用嵌入式QT进行TCP/IP的网络通信应用程序开发,对于TCP客户端,只需要关注QT提供的QTcpSocket类,这个类继承于QAbstractSocket类,在QAbstractSocket类里面提供了一系列的网络操作接口函数,
如:连接服务器connectToHost()、断开与服务器的连接disconnectFromHost(),等等。提供各种信号(connected()、disconnected()、stateChanged())与槽函数,方便应用开发者调用。具体可以参阅 QtNetwork/qabstractsocket.h 文件的内容。

目标:使用QT提供的TCP/IP网络通信类,实现一个简单的TCP客户端(TCP-Client)
功能:
(1)开发板界面显示开发板的网络IP地址。
(2)可手动输入需要连接的服务器IP和端口。
(3)界面显示TCP客户端的连接状态。(连接成功,断开连接,连接出错)
(4)界面显示TCP客户端的收发数据,并提供清屏按钮。
(5)提供手动发送按钮和自动发送按钮。

创建一个tcp_client.h文件,编写一个TCP_Client类继承于QTcpSocket,TCP_Client类提供了一些客户端经常用的操作函数,如连接服务器,获取本机IP,处理连接状态,等等。类的具体实现如下图所示:

  1. #define TCP_CONNECTED        "CONNECTED"
  2. #define TCP_DISCONNECTED     "DISCONNECTED"
  3. #define TCP_CONNECT_ERROR    "CONNECT_ERROR"
  4. class TCP_Client : public QTcpSocket
  5. {
  6.     Q_OBJECT
  7. public:
  8.     TCP_Client(QObject* parent=0);
  9.     ~TCP_Client();
  10.     QString get_local_ipaddr(void);   //获取本机的IP地址
  11.     void connect_server(QString server_ip, int server_port);   //连接服务器函数
  12.     void disconnect_server(void);  //断开与服务器的连接
  13.     void tcp_client_send_data(QByteArray arr_data);    //客户端向服务器发送数据
  14.     void tcp_client_send_data(QString str_data);    //客户端向服务器发送数据
  15. public slots:
  16.     void slot_tcp_client_connected(void);  //客户端连接成功的槽函数
  17.     void slot_tcp_client_disconnected(void);  //客户端断开连接的槽函数
  18.     void slot_tcp_client_connect_error(QAbstractSocket::SocketError);   //客户端连接出错的槽函数
  19.     void slot_tcp_client_recv_data();   //客户端从服务器接收数据
  20. signals:
  21.     void signal_tcp_client_recv_data(QByteArray arr_data);  //发送此信号,通知widget类处理接收到的服务端数据
  22.     void signal_tcp_client_connect_state(QString state);   //发送此信号,通知widget类关于TCP-Client的连接状态
  23. private:
  24.     QTcpSocket *m_tcp_socket;  //QTcpSocket对象,用来进行网络操作
  25. };
复制代码



创建一个tcp_client.cpp文件,这个文件内包含了TCP_Client类里面的所有函数实现。有关tcp_client.cpp的具体内容,请参阅源码。

Qt应用程序启动时,跟C语言一样,都是以main函数作为入口。(当然了,真正的程序启动入口并不是main函数,这里忽略了main函数之前的一系列复杂过程,应用程序呈现给开发者的,一般都是以main函数作为入口)。
以下是Qt应用程序的main函数入口。

  1. int main(int argc, char *argv[])
  2. {
  3.     QApplication a(argc, argv);
  4.     Widget w;
  5.     w.show();
  6.     return a.exec();
  7. }
复制代码


这个main函数比较简单,里面定义了一个QApplication和Widget对象,通过Widget::show()函数显示窗体,然后执行QApplication::exec()函数把整个应用程序加入Qt的事件队列,不断循环。

在Qt的界面应用程序中,对于Widget类型的窗体,其ui都是通过QWidget类进行构建,在widget.cpp文件中,针对本工程,Widget类的构造函数如下图所示:

  1. Widget::Widget(QWidget *parent) :
  2.     QWidget(parent),
  3.     ui(new Ui::Widget)
  4. {
  5.     ui->setupUi(this);
  6.     ui->pushButton_connect->setCheckable(false);
  7.     ui->pushButton_auto_send_data->setCheckable(false);
  8.     ui->pushButton_send_data->setEnabled(false);         //手动发送数据按钮不可用
  9.     ui->pushButton_auto_send_data->setEnabled(false);    //自动发送数据按钮不可用
  10.     ui->lineEdit_server_ip->setEnabled(true);  //服务器IP可以被输入
  11.     ui->lineEdit_server_port->setEnabled(true); //服务器端口可以被输入
  12.     tcp_client = new TCP_Client();  //创建一个TCP_Client类对象
  13.     ui->label_local_ip_display->setText(tcp_client->get_local_ipaddr());   //显示本机的IP地址
  14.     //连接信号槽,用来处理TCP客户端的连接状态
  15.     connect(tcp_client,SIGNAL(signal_tcp_client_connect_state(QString)),this,SLOT(slot_tcp_client_connect_state(QString)));
  16.     //连接信号槽,用来处理TCP客户端接收到的数据
  17.     connect(tcp_client,SIGNAL(signal_tcp_client_recv_data(QByteArray)),this,SLOT(slot_tcp_client_recv_data(QByteArray)));
  18.     auto_send_timer = new QTimer();     //构建一个TCP自动发送数据的定时器
  19.     connect( auto_send_timer, SIGNAL(timeout()), this, SLOT(slot_auto_send_timer_handler()));  //关联定时器超时槽函数
  20. }


在Widget类的构造函数里面,先对ui里面的某些控件进行配置,比如:在连接按钮点击之前,手动和自动发送数据的按钮不可用,服务器IP和端口可被编辑。
然后创建一个TCP_Client类对象,TCP-Client的一系列操作,如连接服务器,收发数据等等,都是基于这个类对象进行。
程序开始运行的时候,在界面上显示本机的IP地址,并连接tcp-client对象提供的信号槽。最后,构建一个定时器对象用于数据的自动发送,定时器对象在构建时,并没有启动计时。

先在windows7上运行服务器端的程序,设置好监听的IP和端口。imx6ul板卡上的客户端应用程序启动后,设置好需要连接的服务器参数,点击 [CONNECT] 按钮,程序就会调用该按钮的槽函数void Widget::on_pushButton_connect_clicked(),函数的实现内容如下图所示:

  1. //点击此按钮,连接服务器
  2. void Widget::on_pushButton_connect_clicked()
  3. {
  4.     QString server_ip;
  5.     int server_port;
  6.     bool ok;
  7.     if(ui->pushButton_connect->isCheckable())      //客户端处于连接状态
  8.     {
  9.         tcp_client->disconnect_server();
  10.     }
  11.     else     //客户端处于断开状态
  12.     {
  13.         //检查服务器IP和服务器端口是否参数有效
  14.         if(ui->lineEdit_server_ip->text().isEmpty() || ui->lineEdit_server_port->text().isEmpty())
  15.         {
  16.             ui->label_connect_status->setText(QString("params error!"));
  17.             QMessageBox::information(this,"Server Params","Server Params Error!");
  18.             return;
  19.         }
  20.         else
  21.         {
  22.             server_ip = ui->lineEdit_server_ip->text();
  23.             server_port = ui->lineEdit_server_port->text().toInt(&ok,10);
  24.             tcp_client->connect_server(server_ip,server_port);   //根据指定的ip和端口,连接服务器
  25.         }
  26.     }
  27. }



点击按钮后,分两种情况,需要判断当前的客户端网络状态是连接还是断开。如果客户端处于连接状态,则点击按钮后,断开客户端与服务器的连接。
如果客户端处于断开状态,则点击按钮后,先检查输入的参数是否有效,如果参数有效,则启动客户端与服务器的连接。客户端与服务器的连接函数connect_server(),如下图所示:

  1. //连接服务器函数
  2. void TCP_Client::connect_server(QString server_ip,int server_port)
  3. {
  4.     if(m_tcp_socket)
  5.     {
  6.         m_tcp_socket->connectToHost(server_ip,server_port,QTcpSocket::ReadWrite); //尝试连接服务器
  7.         //建立信号槽,接收连接成功的信号
  8.         connect(m_tcp_socket,SIGNAL(connected()),this,SLOT(slot_tcp_client_connected()));
  9.         //建立信号槽,接收连接失败的信号
  10.         connect(m_tcp_socket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slot_tcp_client_connect_error(QAbstractSocket::SocketError)));
  11.     }
  12. }
  13. //断开与服务器的连接
  14. void TCP_Client::disconnect_server(void)
  15. {
  16.     if(m_tcp_socket)
  17.         m_tcp_socket->disconnectFromHost();   //断开与服务器的连接
  18. }



客户端与服务器连接过程中,由于在TCP-Client类里面绑定了连接状态的信号槽,因此,连接状态改变后,系统会发送相应的信号,然后调用对应的槽函数进行处理。
因为需要把连接状态显示在界面上,因此,需要在Widget类中,编写一个处理连接状态的槽函数,这个槽函数处理了CONNECTED,DISCONNECTED和CONNECT_ERROR这三种状态。如下图所示:

  1. //客户端连接状态的信号槽
  2. void Widget::slot_tcp_client_connect_state(QString state)
  3. {
  4.     if(state == TCP_CONNECTED)    //TCP客户端处于连接状态
  5.     {
  6.         ui->pushButton_connect->setCheckable(true);
  7.         ui->pushButton_connect->setText(trUtf8("DISCONNECT"));
  8.         //连接成功后,服务器的IP和端口不可以再被编辑
  9.         ui->lineEdit_server_ip->setEnabled(false);
  10.         ui->lineEdit_server_port->setEnabled(false);
  11.         //连接成功后,客户端的发送数据按钮和自动发送按钮可被使用
  12.         ui->pushButton_send_data->setEnabled(true);
  13.         ui->pushButton_auto_send_data->setEnabled(true);
  14.         ui->label_connect_status->setText("connect success");
  15.     }
  16.     else if(state == TCP_DISCONNECTED)   //TCP客户端处于断开状态
  17.     {
  18.         ui->pushButton_connect->setCheckable(false);
  19.         ui->pushButton_connect->setText(trUtf8("CONNECT"));
  20.         //连接断开后,服务器的IP和端口可以再被编辑
  21.         ui->lineEdit_server_ip->setEnabled(true);
  22.         ui->lineEdit_server_port->setEnabled(true);
  23.         //连接断开后,客户端的发送数据按钮和自动发送按钮不可被使用
  24.         ui->pushButton_send_data->setEnabled(false);
  25.         ui->pushButton_auto_send_data->setEnabled(false);
  26.         //自动发送定时器要关闭
  27.         ui->pushButton_auto_send_data->setCheckable(false);
  28.         ui->pushButton_auto_send_data->setText(trUtf8("START_AUTO_SEND"));
  29.         auto_send_timer->stop();
  30.         ui->label_connect_status->setText("disconnect success");
  31.     }
  32.     else if(state == TCP_CONNECT_ERROR)   //TCP客户端连接出错
  33.     {
  34.         ui->pushButton_connect->setCheckable(false);
  35.         ui->pushButton_connect->setText(trUtf8("CONNECT"));
  36.         ui->lineEdit_server_ip->setEnabled(true);
  37.         ui->lineEdit_server_port->setEnabled(true);
  38.         ui->pushButton_send_data->setEnabled(false);
  39.         ui->pushButton_auto_send_data->setEnabled(false);
  40.         ui->label_connect_status->setText("connect error");
  41.     }
  42. }



每点击一次手动发送按钮 [tcp_send_data],客户端将会发送一包数据到服务端。点击自动发送按钮 [START_AUTO_SEND] 按钮,客户端将启动定时器,并以1秒的间隔向服务端发送数据。
手动发送函数和自动发送函数,如下图所示:

  1. //手动发送数据按钮
  2. void Widget::on_pushButton_send_data_clicked()
  3. {
  4.     tcp_client->tcp_client_send_data(QString("helloworld"));
  5.     display_tcp_client_tx_data(QString("helloworld"));
  6. }
  7. //自动发送数据按钮
  8. void Widget::on_pushButton_auto_send_data_clicked()
  9. {
  10.     if(ui->pushButton_auto_send_data->isCheckable())
  11.     {
  12.         ui->pushButton_auto_send_data->setCheckable(false);
  13.         ui->pushButton_auto_send_data->setText(trUtf8("START_AUTO_SEND"));
  14.         auto_send_timer->stop();   //关停定时器
  15.     }
  16.     else
  17.     {
  18.         ui->pushButton_auto_send_data->setCheckable(true);
  19.         ui->pushButton_auto_send_data->setText(trUtf8("STOP_AUTO_SEND"));
  20.         auto_send_timer->start(1000);   //启动定时器,以1秒的频率自动发送数据
  21.     }
  22. }



客户端的发送数据函数tcp_client_send_data(QString),是直接调用了QIODevice::write()进行发送的。我们用面向对象多态的思维,编写两个发送函数,可以分别以QByteArry或QString类型的参数进行数据发送,如下图所示:

  1. //客户端向服务器发送数据,以QByteArray发送
  2. void TCP_Client::tcp_client_send_data(QByteArray arr_data)
  3. {
  4.     if(m_tcp_socket)
  5.         m_tcp_socket->write(arr_data);
  6. }
  7. //客户端向服务器发送数据,以QString格式发送
  8. void TCP_Client::tcp_client_send_data(QString str_data)
  9. {
  10.     if(m_tcp_socket)
  11.         m_tcp_socket->write(str_data.toLatin1().data(),str_data.length());
  12. }



客户端的接收数据函数,是通过信号槽机制来实现的,当Widget类对象接收到TCP-Client类发送的信号signal_tcp_client_recv_data(QByteArray),就调用槽函数处理接收到的数据,如下图所示:

  1. //处理TCP客户端接收到的数据
  2. void Widget::slot_tcp_client_recv_data(QByteArray data_recv)
  3. {
  4.     QString str_display;
  5.     str_display.prepend(data_recv);
  6.     display_tcp_client_rx_data(str_display);   //显示TCP客户端接收到的数据
  7. }



在TCP-Client类对象中,客户端是通过槽函数slot_tcp_client_recv_data()进行网络数据接收的,这个槽函数绑定了QIODevice::readyRead()信号,
一旦底层的IO有网络数据接收,则会调用该槽函数处理,然后这个槽函数会把数据从底层驱动的缓冲区中把数据全部读出,再发送signal_tcp_client_recv_data(QByteArray),通知Widget类进行处理。
在这里,可能大家会有一个疑惑,为什么不在这个槽函数直接处理数据呢?那是因为考虑到了软件的封装性。TCP-Client类只负责接收数据,然后再把接收到的数据通过信号槽传递出去,至于数据怎样处理,则应该在其他的数据handle类里面进行。
比如,这个客户端只进行数据显示,则可以在Widget类里面处理数据,只需要把Widget类里面的数据处理槽函数与TCP-Client类里面的信号绑定就行了。TCP-Client类里面的槽函数slot_tcp_client_recv_data()如下图所示:

  1. //客户端从服务器接收数据
  2. void TCP_Client::slot_tcp_client_recv_data()
  3. {
  4.     //qDebug() << ">>> void TCP_Client::slot_tcp_client_recv_data() >>>";
  5.     QByteArray arr_data_recv;
  6.     arr_data_recv.resize(m_tcp_socket->bytesAvailable());
  7.     arr_data_recv = m_tcp_socket->readAll();
  8.     emit signal_tcp_client_recv_data(arr_data_recv);
  9. }



至此,整个TCP-Client连接服务器以及数据收发过程已经描述完成。这个工程只是简单地描述了TCP-Client建立通信和数据收发的简单过程。在真正的TCP-Client网络应用程序中,还需要处理很多突发的网络情况。
如:连接过程中的错误处理,心跳包机制,服务端强行断开连接后客户端的处理,数据粘包与断包,数据接收队列,等等。开发者应在工程开发中不断积累经验,才能开发出稳定可靠的网络应用程序。

题外知识:
      很多初学者可能会对服务器和客户端没有什么概念,不知道怎样理解服务端/客户端这两个角色,个人觉得,要记住关键的一点:客户端是请求服务的,服务器是提供服务的。
举一个简单而通俗的例子:汽车去加油站加油。
把汽车比喻为TCP-Client客户端,把加油站的加油机比喻为TCP-Server服务器。当汽车(TCP-Client)需要向加油机(TCP-Server)请求加油服务时,
则需要先知道加油站在哪(服务器的IP地址),在哪台加油机(服务器端口)上加油,当指定好加油站和具体的加油机后,就可以向加油机请求连接(向汽车插上加油枪)了。
But,总会有特殊情况的时候,比如,当该加油机没有油而导致加不了油(连接不上)了,那么,加油机(服务器)就会通知请求加油的汽车(客户端)进行处理,(这里就涉及到连接不上的情况了)。
当汽车加完油之后,就像是服务端已经提供完服务,那么,汽车(客户端)就可以主动端开与加油机(服务端)的连接了。

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

嵌入式Linux应用程序开发-TCP-IP网络通信应用程序 的相关文章

  • 基于51单片机的密码锁设计

    研究内容 本系统由STC89C52单片机系统 xff08 主要是STC89C52单片机最小系统 xff09 4 4矩阵键盘 LCD1602显示和报警系统等组成 xff0c 具有设置 修改六位用户密码 超次报警 超次锁定 密码错误报警等功能
  • 【gcc】gcc优化等级 -O1 -O2 -O3 -Os -Ofast -Og|gcc关闭优化

    目录 优化等级 O1 O2 O3 Os Ofast Og cmake 生成 debug和 release 版 Cmake设置优化等级 Debug和Release 方案 About table About question gcc g 43
  • 嵌入式期末复习题(二)

    考试题型 一 选择题 每小题2分 xff0c 15题 xff0c 共30分 二 填空题 每题2分 xff0c 10题 xff0c 共20分 三 简答题 每题5分 xff0c 4题 xff0c 共20分 四 分析题 每题5分 xff0c 3题
  • 嵌入式期末复习题(三)

    1嵌入式系统的定义 嵌入式系统是用于控制 监视或辅助操作机器和设备的装置 嵌入式系统是以应用为中心 xff0c 以计算机技术为基础 xff0c 软硬件可裁剪 xff0c 适应应用系统对功能 可靠性 成本 体积和功耗等严格要求的专用计算机系统
  • 解决Ubuntu 网速慢的问题

    Ubuntu 网速慢 xff0c 主要是把时间浪费在域名解析上 我们可以用dnsmasq解决这问题 具体如下 xff1a 1 安装dnsmasq 命令 sudo apt get install dnsmasq 2 编辑dnsmasq的配置文
  • C++中的char,char*,char[]

    char C 43 43 中的char是字符的意思 xff0c 可以用例如 39 a 39 来表示 xff0c 每个字符串string都是由很多个单独的字符char组成 char char 是一个指针 xff0c 例如 xff1a char
  • VSCode 运行C++程序

    0 省流自强版 本方法来自以下两个参考链接 xff0c 可自行参照去执行安装 xff1a 1 https code visualstudio com docs languages cpp 2 https www youtube com wa
  • 了解CV和RoboMaster视觉组(四)视觉组使用的硬件

    NeoZng neozng1 64 hnu edu cn 4 视觉组接触的硬件 虽然别人总觉得视觉组就是整天对着屏幕臭敲代码的程序员 xff0c 实际上我们也会接触很多的底层硬件与传感器 xff0c 在使用硬件的同时很可能还需要综合运用其他
  • VINS-RGBD运行指令

    创建工程VINS RGBD catkin ws 将代码放入src文件夹当中 git clone https github com STAR Center VINS RGBD 进行编译 cd VINS RGBD catkin ws catki
  • ubuntu16.04安装realsense D435i驱动及固件

    安装Realsense SDK xff1a 1 下载source并且确定git版本 xff1a 1 git clone https github com IntelRealSense librealsense xff08 下载源 xff09
  • ROS入门(七)——仿真机器人三(Gazebo+Xacro)

    所用的学习链接 xff1a 奥特学园 ROS机器人入门课程 ROS理论与实践 零基础教程P271 277 以上视频笔记见http www autolabor com cn book ROSTutorials 前文参考 ROS入门 五 仿真机
  • ROS入门(九)——机器人自动导航(介绍、地图、定位和路径规划)

    所用的学习链接 xff1a 奥特学园 ROS机器人入门课程 ROS理论与实践 零基础教程P289 314 以上视频笔记见http www autolabor com cn book ROSTutorials 一 介绍 官方链接 xff1a
  • Keil工程添加源文件和头文件(.c和.h)的方法

    在此把Keil项目添加源文件和头文件的方法做个记录 xff1a 1 Keil项目添加源文件和头文件的方法之一 1 1 右键点击项目名称 xff0c 弹出菜单中选择Add Group xff0c 我们把所有需要添加的源文件都放在这个Group
  • 漂亮的html表格

    原文 xff1a http www textfixer com resources css tables php css table01 一个像素边框的表格 xff1a Info Header 1 Info Header 2 Info He
  • SIPp之认证注册

    欢迎大家转载 xff0c 为保留作者成果 xff0c 转载请注明出处 xff0c http blog csdn net netluoriver xff0c 有些文件在资源中也可以下载 xff01 如果你没有积分 xff0c 可以联系我 xf
  • HTTP:DIGEST认证的请求和响应报文

    以下是HTTP DIGEST认证的请求和响应报文的例子 xff0c 供以后参考 IE first request GET boe checkedServlet HTTP 1 1 Accept image gif image jpeg ima
  • Linux配置篇 | Ubuntu配置apt镜像源

    以下以 Ubuntu18 04 LTS 为例 xff0c 也适用于 Ubuntu 其他版本 一 修改apt镜像源 xff08 1 xff09 备份apt配置文件 xff1a cp etc apt sources list etc apt s
  • STC89C52RC单片机额外篇 | 04 - 认识头文件<intrins.h>与_nop_函数

    1 lt intrins h gt 头文件 头文件 lt intrins h gt 在我们51单片机日常开发中经常使用 xff0c 特别是 nop 函数 xff0c 以下是 lt intrins h gt 的内容 xff1a span cl
  • HTTP协议详解 - 通过C++实现HTTP服务剖析HTTP协议

    前言 C C 43 43 程序员一般很少会接触到HTTP服务端的东西 xff0c 所以对HTTP的理解一般停留在理论 本文章实现通过C 43 43 实现了一个http服务 xff0c 可以通过代码对HTTP协议有更深的理解 xff0c 并且
  • GIT 中如何打标签

    前言0x1 GIT 标签常用指令0x2 轻量标签0x3 附注标签0x4 远程仓库中的标签 前言 在我们开发的过程中 xff0c 可能经过多次 commit 提交才会确定一个版本 xff0c 那么除了用 commit comments 来标识

随机推荐

  • 用VSCode开发C++项目

    写在前面 最近在新学C 43 43 xff0c 又不想用VisualStudio那么庞大的IDE xff0c VS体量稍微有那么点笨重 xff08 主要还是因为穷 xff0c 没钱换电脑 xff0c 目前的电脑开个VS要个两三分钟 xff0
  • petalinux2018.3 error 记录

    petalinux config get hw description 61 报错 INFO sourcing bitbake ERROR Failed to source bitbake ERROR Failed to config pr
  • petalinux 编译,源码编译

    1 测试环境 Ubuntu 16 04PetaLinux 2019 1PetaLinux 2019 1 ZCU106 BSPZCU106 2 PetaLinux介绍 PetaLinux是Xilinx基于Yocto推出的Linux开发工具 Y
  • Optitrack Motive软件安装及使用说明

    Motive 软件安装程序 http www naturalpoint com optitrack downloads motive html 安装Motive需要安装两个底层插件 xff0c Directx aug2009 redist
  • Failed to get convolution algorithm. This is probably because cuDNN failed to initialize

    Failed to get convolution algorithm This is probably because cuDNN failed to initialize from tensorflow compat v1 import
  • C语言---整型字符串转换

    C语言提供了几个标准库函数 xff0c 可以将任意类型 整型 长整型 浮点型等 的数字转换为字符串 以下是用itoa 函数将整数转 换为字符串的一个例子 xff1a include lt stdio h gt include lt stdl
  • 约瑟夫环(C语言单项循环链表)

    约瑟夫环 C 语言单项循环链表 约瑟夫环 问题描述 xff1a 约瑟夫问题的一种描述是 xff1a 编号为1 xff0c 2 xff0c xff0c n 的n 个人按顺时针方向围坐一圈 xff0c 每人持一个密码 xff08 正整数 xff
  • 交换机VLAN的定义、意义以及划分方式

    什么是VLAN 虚拟网技术 xff08 VLAN xff0c Virtual Local Area Network xff09 的诞生主要源于广播 广播在网络中起着非常重要的作用 xff0c 如发现新设备 调整网络路径 IP地址租赁等等 x
  • coredump简介与coredump原因总结

    coredump简介与coredump原因总结 什么是coredump xff1f 通常情况下coredmp包含了程序运行时的内存 xff0c 寄存器状态 xff0c 堆栈指针 xff0c 内存管理信息等 可以理解为把程序工作的当前状态存储
  • 嵌入式设备web服务器比较

    现在在嵌入式设备中所使用的web服务器主要有 xff1a boa thttpd mini httpd shttpd lighttpd goaheand appweb和apache等 Boa 1 介绍 Boa诞生于1991年 xff0c 作者
  • memfd.c:40:12: error: static declaration of ‘memfd_create’ follows non-static declaration

    qemu编译安装出错 xff1a memfd c 40 12 error static declaration of memfd create follows non static declaration 修改 xff1a a util m
  • windows10 驱动开发环境 VS2019+WDK10

    windows10 驱动开发环境 1 下载SDK https developer microsoft com zh cn windows downloads windows 10 sdk 通用驱动demo xff1a https githu
  • 在用户配置文件中添加 IDF_PATH 和 idf.py PATH

    在用户配置文件中添加 IDF PATH 和 idf py PATH CMake 英文 注解 本文档将介绍如何使用 CMake 编译系统 目前 xff0c CMake 编译系统仍处于预览发布阶段 xff0c 如您在使用中遇到任何问题 xff0
  • error C3861: “gets”: 找不到标识符

    error C3861 gets 找不到标识 把 gets 改成 gets s 用VS2015打开一个win32工程 xff0c 生成解决方案失败 报错信息 xff1a 命令行 error D8016 ZI 和 Gy 命令行选项不兼容 选中
  • ROS和Optitrack通信

    ROS xff1a indigo Ubuntu xff1a 14 04 目的 xff1a 一台计算机通过Optitrack获得刚体 xff08 crazyflie2 0 xff09 的姿态信息并广播到同一局域网的其他计算机上 xff08 如
  • 运算放大电路(三)-加法器

    加法器 由虚短知 xff1a V 61 V 43 61 0 a 由虚断及基尔霍夫定律知 xff0c 通过R2与R1的电流之和等于通过R3的电流 xff0c 故 V1 V R1 43 V2 V R2 61 Vout V R3 b 代入a式 x
  • 一个嵌入式硬件高手的设计心得

    一 xff1a 成本节约 现象一 xff1a 这些拉高 拉低的电阻用多大的阻值关系不大 xff0c 就选个整数5K吧 点评 xff1a 市场上不存在5K的阻值 xff0c 最接近的是 4 99K xff08 精度1 xff09 xff0c
  • 跟着我从零开始入门FPGA(一周入门系列)第五

    5 同步和异步设计 前面已有铺垫 xff0c 同步就是与时钟同步 同步就是走正步 xff0c 一二一 xff0c 该迈哪个脚就迈那个脚 xff0c 跑的快的要等着跑的慢的 异步就是搞赛跑 xff0c 各显神通 xff0c 尽最大力量去跑 x
  • 硬件原理图设计规范(二)

    1 可编程逻辑器件 编号 级别 条目内容 备注 1 推荐 FPGA的LE资源利用率要保证在50 xff5e 80 之间 xff0c EPLD的MC资源的利用率要保证在50 xff5e 90 之间 对于FPGA中的锁相环 RAM 乘法器 DS
  • 嵌入式Linux应用程序开发-TCP-IP网络通信应用程序

    作为全世界最优秀的开源操作系统 xff0c Linux内部已经集成了强大的网络协议栈 xff0c 并向应用层提供丰富的系统调用 xff0c 开发者可以基于通用的系统调用接口 xff0c 使用Linux内核提供的网络功能 如果要分析Linux