Linux高级编程——网络通信实现TCP(1)

2023-05-16

基于TCP协议的文件传输(套接字)实例:

客户端:只用于收文件;
执行命令:./执行文件名 IP Port

// 客户端 输入 ./执行文件 IP Port
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>


int main(int argc, char** argv)
{
    // 第一步:创建一个新的套接字
    int sock = socket(AF_INET, SOCK_STREAM, 0);

    if(-1 == sock)
    {
        perror("socket");
        return 1;
    }


    // 第三步:连接服务器

    struct sockaddr_in srv_addr;
    srv_addr.sin_family = AF_INET;
    srv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    srv_addr.sin_port = htons(atoi(argv[2]));

    if(-1 == connect(sock, (struct sockaddr*)&srv_addr, sizeof(srv_addr)))
    {
        perror("connect");
        return 1;
    }

    // 第四步:收发数据

    // 发送数据
    char msg[300];
    int ret;
    ret= recv(sock,msg,sizeof(msg), 0);

    int fd = open("msg",O_WRONLY | O_CREAT);
    
    while(1)
    {
        ret = recv(sock, msg, sizeof(msg), 0);
        
        if(ret <= 0) break; //0为正常断开,-1为异常断开
        write(fd,msg,sizeof(ret));
    }

    close(fd);
    // 第五步:端开连接
    close(sock);
    
    return 0;
}

服务器端一:面向所有人,利用while循环发送文件,不能同时向多人发送;
执行命令:./执行文件名 传输文件名

//服务器端:循环等待发送数据 ./执行文件  文件(不能是文件夹)
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>


int main(int argc, char** argv)
{
    //socket 函数:创建一个新套接字
    int sock_listen = socket(AF_INET, SOCK_STREAM, 0);

    if(-1 == sock_listen)
    {
        perror("socket");
        return 1;
    }

    // 第二步:绑定地址
    // 指定地址信息
    struct sockaddr_in myaddr;
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = INADDR_ANY;

    myaddr.sin_port = htons(8888); 
 
    // 将上面指定的地址和套接字绑定
    if(-1 == bind(sock_listen, (struct sockaddr*)&myaddr, sizeof(myaddr)))
    {
        perror("bind");
        return 1;
    }

    // 第三步:监听
    if(-1 == listen(sock_listen, 5))
    {
        perror("listen");
        return 1;
    }

    while(1)
    {
        // 第四步:接受客户端连接请求

        //accept(sock_listen, NULL, NULL);  // 如果对客户端地址信息不感兴趣

        // 如果想获取当前客户端的地址信息,就使用下面的方式
        struct sockaddr_in client_addr;
        socklen_t len = sizeof(client_addr);

       
        int sock_conn = accept(sock_listen, (struct sockaddr*)&client_addr, &len);

        if(-1 == sock_conn)
        {
            perror("accept");
            continue;
        }

        printf("\n%s:%hu 已连接...\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        // 第五步:收发数据

        // 发送数据
        char file_name[300];
        char msg[1024];
        int ret;
        unsigned long cnt1 = 0, cnt2 = 0;
        time_t start, end;
        char* p = NULL;

        p = strrchr(argv[1], '/');

        if(NULL == p)
        {
            strcpy(file_name, argv[1]);
        }
        else
        {
            strcpy(file_name, p + 1);
        }

        send(sock_conn, file_name, sizeof(file_name), 0);

        int fd = open(argv[1], O_RDONLY);

        printf("正在努力发送文件...\n");

        time(&start);

        while((ret = read(fd, msg, sizeof(msg))) > 0)
        {
            cnt1 += ret;

            ret = send(sock_conn, msg, ret, 0);
            //write(sock_conn, msg, sizeof(msg));  // 和上面的写法等效

            if(ret == -1) 
            {
                printf("发送文件失败!\n");
                break;
            }

            cnt2 += ret;
        }

        if(cnt1 != 0 && cnt1 == cnt2)
        {
            time(&end);
            printf("发送文件成功!(耗时 %d 秒)\n", end - start);
        }

        // 第六步:断开客户端连接
        close(sock_conn);
    }

    // 第七步:关闭监听套接字
    close(sock_listen);
    
    return 0;
}

方法二:利用fork,使用多进程方式提高效率

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>


int main(int argc, char** argv)
{
    //socket 函数:创建一个新套接字
    // 参数意义:
    // 第一个参数:地址家族,通常是 AF_INET
    // 第二个参数:套接字类型,通常有两种:SOCK_STREAM(流套接字,用于 TCP 协议通信) 和 SOCK_DGRAM(数据报式套接字,用于 UDP 协议通信)
    // 第三个参数:通常为 0, 表示使用默认协议。
    // 返回值为新套接字的文件描述符,如果失败则为 -1

    // 第一步:创建一个新的监听套接字
    int sock_listen = socket(AF_INET, SOCK_STREAM, 0);

    if(-1 == sock_listen)
    {
        perror("socket");
        return 1;
    }

    // 第二步:绑定地址

    // 指定地址信息
    struct sockaddr_in myaddr;
    myaddr.sin_family = AF_INET;            // 指定地址家族为 Internet 地址家族
    myaddr.sin_addr.s_addr = INADDR_ANY;    // 指定 IP 地址为本机任意地址
    //myaddr.sin_addr.s_addr = inet_addr("192.168.0.56");    // 指定 IP 地址为本机某个确定的 IP 地址
    myaddr.sin_port = htons(8888);          // 指定端口号为 8888
    // htons:将一个短整型数据从主机字节序(通常是小端)转换为网络字节序(通常是大端)
    // inet_addr:将字符串形式的 IP 地址转换为无符号 32 位整数,并且是网络字节序

    // 将上面指定的地址和套接字绑定
    if(-1 == bind(sock_listen, (struct sockaddr*)&myaddr, sizeof(myaddr)))
    {
        perror("bind");
        return 1;
    }

    // 第三步:监听
    // listen 函数的第二个参数为监听等待队列的长度
    if(-1 == listen(sock_listen, 5))
    {
        perror("listen");
        return 1;
    }

    while(1)
    {
        // 第四步:接受客户端连接请求

        //accept(sock_listen, NULL, NULL);  // 如果对客户端地址信息不感兴趣

        // 如果想获取当前客户端的地址信息,就使用下面的方式
        struct sockaddr_in client_addr;
        socklen_t len = sizeof(client_addr);

        // 调用 accept 函数接收一个客户端连接请求(队头请求)
        // 如果成功,返回值为一个套接字描述符,这个套接字是和该客户端一一对应的
        // 这个套接字专门用于和对应的客户端通信,所以通常称它为连接套接字。
        // 如果当前没有任何客户端连接请求到来,accept 函数将会阻塞当前线程,直到成功接收到一个连接请求或出错
        int sock_conn = accept(sock_listen, (struct sockaddr*)&client_addr, &len);

        if(-1 == sock_conn)
        {
            perror("accept");
            continue;
        }

        pid_t pid = fork();

        if(-1 == pid)
        {
            perror("fork");
            close(sock_conn);
            continue;
        }

        if(pid > 0)
        {
            // 父进程只负责接收客户端连接请求,并创建子进程
            close(sock_conn);
            continue;
        }

        // 子进程负责与对应的客户端通信
        close(sock_listen);

        printf("\n%s:%hu 已连接...\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        // 第五步:收发数据

        // 发送数据
        char file_name[300];
        char msg[1024];
        int ret;
        unsigned long cnt1 = 0, cnt2 = 0;
        time_t start, end;
        char* p = NULL;

        p = strrchr(argv[1], '/');

        if(NULL == p)
        {
            strcpy(file_name, argv[1]);
        }
        else
        {
            strcpy(file_name, p + 1);
        }

        send(sock_conn, file_name, sizeof(file_name), 0);

        int fd = open(argv[1], O_RDONLY);

        printf("正在努力发送文件...\n");

        time(&start);

        while((ret = read(fd, msg, sizeof(msg))) > 0)
        {
            cnt1 += ret;

            ret = send(sock_conn, msg, ret, 0);
            //write(sock_conn, msg, sizeof(msg));  // 和上面的写法等效

            if(ret == -1) 
            {
                printf("发送文件失败!\n");
                break;
            }

            cnt2 += ret;
        }

        if(cnt1 != 0 && cnt1 == cnt2)
        {
            time(&end);
            //printf("发送文件成功!(耗时 %lu 秒,平均网速 %lu B/s)\n", end - start, cnt1 / (end -start));
            printf("发送文件成功!(耗时 %lu 秒)\n", end - start);
        }

        // 第六步:断开客户端连接
        close(sock_conn);

        exit(0);
    }

    // 第七步:关闭监听套接字
    close(sock_listen);
    
    return 0;
}

方法三:利用多线程方式

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>


static const char* file_path = NULL;
static char file_name[300];


static void* send_file(void* arg);


int main(int argc, char** argv)
{
    file_path = argv[1]; 

    char* p = NULL;

    p = strrchr(argv[1], '/');

    if(NULL == p)
    {
        strcpy(file_name, argv[1]);
    }
    else
    {
        strcpy(file_name, p + 1);
    }

    //socket 函数:创建一个新套接字
    // 参数意义:
    // 第一个参数:地址家族,通常是 AF_INET
    // 第二个参数:套接字类型,通常有两种:SOCK_STREAM(流套接字,用于 TCP 协议通信) 和 SOCK_DGRAM(数据报式套接字,用于 UDP 协议通信)
    // 第三个参数:通常为 0, 表示使用默认协议。
    // 返回值为新套接字的文件描述符,如果失败则为 -1

    // 第一步:创建一个新的监听套接字
    int sock_listen = socket(AF_INET, SOCK_STREAM, 0);

    if(-1 == sock_listen)
    {
        perror("socket");
        return 1;
    }

    // 第二步:绑定地址

    // 指定地址信息
    struct sockaddr_in myaddr;
    myaddr.sin_family = AF_INET;            // 指定地址家族为 Internet 地址家族
    myaddr.sin_addr.s_addr = INADDR_ANY;    // 指定 IP 地址为本机任意地址
    //myaddr.sin_addr.s_addr = inet_addr("192.168.0.56");    // 指定 IP 地址为本机某个确定的 IP 地址
    myaddr.sin_port = htons(8888);          // 指定端口号为 8888
    // htons:将一个短整型数据从主机字节序(通常是小端)转换为网络字节序(通常是大端)
    // inet_addr:将字符串形式的 IP 地址转换为无符号 32 位整数,并且是网络字节序

    // 将上面指定的地址和套接字绑定
    if(-1 == bind(sock_listen, (struct sockaddr*)&myaddr, sizeof(myaddr)))
    {
        perror("bind");
        return 1;
    }

    // 第三步:监听
    // listen 函数的第二个参数为监听等待队列的长度
    if(-1 == listen(sock_listen, 5))
    {
        perror("listen");
        return 1;
    }

    while(1)
    {
        // 第四步:接受客户端连接请求

        //accept(sock_listen, NULL, NULL);  // 如果对客户端地址信息不感兴趣

        // 如果想获取当前客户端的地址信息,就使用下面的方式
        struct sockaddr_in client_addr;
        socklen_t len = sizeof(client_addr);

        // 调用 accept 函数接收一个客户端连接请求(队头请求)
        // 如果成功,返回值为一个套接字描述符,这个套接字是和该客户端一一对应的
        // 这个套接字专门用于和对应的客户端通信,所以通常称它为连接套接字。
        // 如果当前没有任何客户端连接请求到来,accept 函数将会阻塞当前线程,直到成功接收到一个连接请求或出错
        int sock_conn = accept(sock_listen, (struct sockaddr*)&client_addr, &len);

        if(-1 == sock_conn)
        {
            perror("accept");
            continue;
        }

        printf("\n%s:%hu 已连接...\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        pthread_t tid;
        if(pthread_create(&tid, NULL, send_file, (void*)(long)sock_conn))
        {
            perror("pthread_create");
            close(sock_conn);
            continue;
        }
    }

    // 第七步:关闭监听套接字
    close(sock_listen);
    
    return 0;
}


// 负责给对应客户端发送文件的线程
void* send_file(void* arg)
{
    pthread_detach(pthread_self());

    int sock_conn = (int)(long)arg;

    // 第五步:收发数据

    // 发送数据
    char msg[1024];
    int ret;
    unsigned long cnt1 = 0, cnt2 = 0;
    time_t start, end;

    send(sock_conn, file_name, sizeof(file_name), 0);

    int fd = open(file_path, O_RDONLY);

    printf("正在努力发送文件...\n");

    time(&start);

    while((ret = read(fd, msg, sizeof(msg))) > 0)
    {
        cnt1 += ret;

        ret = send(sock_conn, msg, ret, 0);
        //write(sock_conn, msg, sizeof(msg));  // 和上面的写法等效

        if(ret == -1) 
        {
            printf("发送文件失败!\n");
            break;
        }

        cnt2 += ret;
    }

    if(cnt1 != 0 && cnt1 == cnt2)
    {
        time(&end);
        //printf("发送文件成功!(耗时 %lu 秒,平均网速 %lu B/s)\n", end - start, cnt1 / (end -start));
        printf("发送文件成功!(耗时 %lu 秒)\n", end - start);
    }

    // 第六步:断开客户端连接
    close(sock_conn);

    pthread_exit(NULL);
}

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

Linux高级编程——网络通信实现TCP(1) 的相关文章

  • STM32软件模拟iic驱动oled(显示汉字,图片)(二)

    在上一篇介绍的软件模拟iic及iic源码后 xff0c 今天来实现显示汉字与图片以及各个函数的介绍 一 函数介绍及使用 1 显示字符 OLED ShowStr unsigned char x unsigned char y unsigned
  • CMake笔记--find_package 指定路径

    1 find package 指定路径 1 1 命令 find package span class token punctuation span span class token operator lt span PackageName
  • TM4C123系列(四)————UART串口通信

    一 实验简介 使用TM4C123的串口通信功能实现单片机与PC端通信 二 UART介绍 TM4C123有八个串口 xff0c 其中UART0已经与USB集成 xff0c UART0建议只用来和PC端通信 xff0c 不要与外界通信 除此之外
  • STM32软件模拟iic驱动oled(显示汉字,图片)(一)

    一 iic驱动模式 1 硬件驱动 xff1a 所谓硬件驱动就是使用STM32板子上固定的iic接口 xff0c 但是由于板载iic数量有限 xff0c 且大多和别的外设有引脚复用 xff0c 在别的外设使用的情况下还得通过重映射引到别的引脚
  • 初识ESP8266(二)————搭建网络服务器实现远程控制

    一 实验介绍 8266搭建网络服务器 xff0c 通过同一wifi信号下的终端访问ESP8266IP地址 xff0c 对开发板进行控制 二 代码 1 esp8266 server begin 作用 xff1a 启动网络服务 xff0c 搭建
  • 关于舵机的漂移与不听指挥乱动的问题

    在电赛E题中控制二维云台中出现了两个问题 xff0c 也是好不容易才发现原因然后解决的 一 舵机不听指挥乱动 没有与单片机共地 舵机有三条线 xff0c 分别是正负极和信号线 用来输入PWM信号 xff0c 因为舵机所需要的驱动电压比较大
  • 蓝桥杯嵌入式(STM32F103RBT6)备赛手册(一)

    文章目录 一 基础篇一 点亮LED二 驱动蜂鸣器三 Systick定时器四 定时器五 独立按键 三行代码消抖六 IIC协议七 LCD显示八 串口接收与发送九 ADC采样十 RTC时钟十一 PWM输出及输入捕获 一 基础篇 一 点亮LED 由
  • Asahi Linux的Alpha 版本已匹配Mac 设备

    导读Asahi Linux 是一个旨在将 Linux 移植到配备 Apple Silicon 芯片 Mac 设备上的项目 xff0c 项目的目标不仅仅是让 Linux 能够在这些设备上运行 xff0c 而是要将它打磨到可以用作日常操作系统的
  • Linux的优缺点

    导读Linux 是一个流行词 xff0c 你到处都能听到与 Linux 相关的内容 人们在技术论坛上讨论它 Linux 是课程中的一部分 xff1b 你最喜欢的 YouTube 技术主播在兴奋地展示构建他们的 Linux 内核 xff1b
  • 不敢想象!Vim使用者的“大脑”竟是这样

    原始状态 我曾经观看过小提琴家非常有激情地拉弦演奏 xff0c 我有了这种想法 xff1a 也许我投入到文本编辑器中的脑细胞数量和他为投入所喜好的乐器的演奏中差不多吧 我还有种奇异的想象 xff0c 当他独奏的时候 xff0c 脑中的核磁共
  • Windows 10的子系统不是非Ubuntu不可

    Ubuntu 的制造商 Canonical 早已和微软进行合作 xff0c 让我们体验了极具争议的 Bash on Windows 外界对此也是褒贬不一 xff0c 许多 Linux 重度用户则是质疑其是否有用 xff0c 以及更进一步认为
  • 绝对空前!!!互联网史上的最大ddos攻击惊艳登场

    美国遭遇史上最大黑客攻击 xff0c 知名网站全部瘫痪 全世界一半的网络被黑客攻陷 xff0c 大网站无一幸免 就在 xff08 10月22日 xff09 xff0c 美国早上我们见证了互联网建立以来的最大ddos攻击 xff0c twit
  • snprintf()函数探讨

    printf sprintf snprintf 区别 先贴上其函数原型 printf const char format 格式化输出字符串 xff0c 默认输出到终端 stdout sprintf char dest const char
  • 3D创作元素将入住下一代Windows 10和HoloLens中

    新 Windows 10 将会带来崭新的 3D 特性 xff0c 任何用户都可以通过内置的工具来制作发布有关 3D 增强现实 AR 和混合现实 mixed reality 的游戏和素材 北京时间 10 月 26 号晚 10 点 xff0c
  • Chrome 又不支持 HTTP/2 网站的原因

    导读昨晚偶尔清理 Chrome 插件时发现我的 HTTP 2 and SPDY indicator 插件好像好久没亮了 这个插件在你访问到一个支持 HTTP 2 xff08 或之前的 SPDY 协议 xff09 的网站时会点亮 xff0c
  • Win10/11后:Linux启动AMD处理器fTPM出现同款间歇性卡顿

    导读早在2022年3月 xff0c AMD就曾确认 xff0c 在Win10与Win11系统下 xff0c 开启锐龙处理器的fTPM xff0c 将可能导致系统出现间歇性的卡顿 死机等情况 xff0c 并发布BIOS更新进行了修复 但出乎预
  • 12 个好用且不花钱的网络监控工具

    导读要让一个多级机构运行良好而且平稳的话 xff0c 一个非常艰巨重大的任务就是做好网络管理 每个机构都配备专门的人员 xff0c 即网络分析师 xff0c 来进行网络管理 他们 使用了 许多工具来监视网络的运行状况 xff0c 并查看网络
  • Solus Linux 改变发展方向

    导读Solus 是一个独立开发的 Linux 发行版 xff0c 它的一大特色就是 Solus 自创的 Budgie 桌面环境 xff08 最新的 Fedora 也已经新增了这个桌面环境 xff09 xff0c 当然用户也可以选择其他常见的
  • 虚拟机与主机互传文件方法分享

    现在虚拟机的使用已经非常普及 xff0c 无论新手学习 xff0c 还是运维工程师搭建虚拟化平台 xff0c 都会使用到虚拟机 对个人用户来说 xff0c 非常方便就能搭建很多操作系统进行学习 xff1b 对企业用户来说更是降低了服务器的硬
  • RethinkDB成为Linux基金会的一员

    导读日前 xff0c RethinkDB项目有了新的动态 Cloud Native Computing基金会 xff08 CNCF xff09 宣布它购买了NoSQL分布式文件存储数据库RethinkDB的源代码版权 xff0c 将授权协议

随机推荐

  • STM32 汇编程序——串口输出 Hello world

    STM32 汇编程序 串口输出 Hello world 一 USART介绍二 Keil项目 xff08 一 xff09 新建项目 xff08 二 xff09 Hello s代码 xff08 三 xff09 编译生成hex文件 三 电路接法四
  • C语言笔记-头文件

    复习 xff1a 1 输出缓冲区 程序输出的数据并没有立即写入 文件 xff0c 而是先存储到输出缓冲区 xff0c 当满足一定条件时才写入文件中 xff1a 1 遇到 39 n 39 2 遇到输入语句 3 缓冲区满4k 4 程序结束 5
  • 不使用strcat()的字符串连接

    问题描述 在不使用strcat 的前提下 xff0c 实现两个字符串的连接 输入形式 以 39 39 为结束符的两行字符串 输出形式 将第一行字符串连接到第二行字符串 xff0c 然后打印输出 样例输入 abc def 样例输出 defab
  • pixhawk 整体架构的认识

    此篇blog的目的是对px4工程有一个整体认识 xff0c 对各个信号的流向有个了解 xff0c 以及控制算法采用的控制框架 PX4自动驾驶仪软件 可分为三大部分 xff1a 实时操作系统 中间件和飞行控制栈 1 NuttX实时操作系统 提
  • 光流定位原理

    无人机上光流定位通常是借助于无人机底部的一个摄像头采集图像数据 xff0c 然后采用光流算法计算两帧图像的位移 xff0c 进而实现对无人机的定位 xff0c 这种定位手段配合GPS可以在室外实现对无人机的精准控制 xff0c 并且在市内没
  • 图形化UDP发包小工具

    文章目录 前言一 构思二 用到的python模块tkiner模块tkiner模块下载 socket模块ThreadPoolExecutor模块导入方式 编码实现客户端服务端代码 三 运行结果客户端发送消息服务端 前言 工具编写用的语言是py
  • C语言之调试技巧(VS2019编译器)

    C语言之调试技巧 xff08 VS2019编译器 xff09 一 什么是调试 xff1f 调试的作用1 1 什么是调试1 2 调试的基本步骤1 3 Debug版本和Release版本的介绍二 Windows环境调试的准备2 1 调试环境的准
  • 怎么在vscode上编写C语言代码

    1 准备工作 xff1a 在vscode的拓展里面下载安装c c 43 43 官方插件 此外 xff0c 需要安装一个c c 43 43 的编译器 MinGW xff0c MinGW 官网下载地址 xff08 点击即可进入官网 xff09
  • Ubuntu20.04系统安装ROS-noetic教程及常见问题的处理

    Ubuntu版本 xff1a 20 04 ROS版本 xff1a Noetic Ninjemys 注 xff1a Ubuntu系统版本要与ROS版本相对应 xff0c 不同版本的Ubuntu系统对应了不同的ROS版本 如Ubuntu20 0
  • 笔记(STM32篇)day2——GPIO及寄存器映射

    目录 一 GPIO结构及模式 1 推挽输出 2 开漏输出 3 复用功能输出 4 上拉 下拉输入 5 复用功能输入与模拟输入 二 寄存器映射 一 GPIO结构及模式 图1 GPIO基本结构 如图1所示为GPIO基本结构 xff0c 右侧I O
  • 笔记(STM32篇)day3——寄存器结构体、端口置位函数

    目录 一些C知识点 1 define和typedef的区别 2 结构体struct 3 结构体中 和 gt 的区别 4 c文件和 h文件的关系 5 防止重复引用 一 寄存器结构体定义 1 定义结构体变量指针 2 寄存器赋值 二 端口置位函数
  • 笔记(STM32篇)day6——按键控制

    目录 一 按键硬件图 1 硬件原理 2 输入方式选择 二 功能实现 1 按键GPIO配置 2 按键扫描函数 3 LED翻转宏定义 4 主程序 参考 一 按键硬件图 1 硬件原理 按键的硬件原理图如图 xff0c 右侧接3 3V xff0c
  • 笔记(STM32篇)day8——系统时钟配置、MCO输出系统时钟

    目录 一 时钟框图 二 配置过程 1 系统时钟配置函数 2 MCO配置 参考 一 时钟框图 下图就是STM32F10x的时钟系统框图 xff0c 此处用的正点原子的图 xff0c 左侧四个蓝色的分别是 xff1a 高速内部RC时钟 xff0
  • pixhawk博客导读

    写的东西有点多 xff0c 写的也有点乱 xff0c 看题目也不知道内容是什么 xff0c 为了方便网友观看自己感兴趣的地方 xff0c 笔者把pixhawk博客归类一下 由于笔者也是边学习边写的 xff0c 难免有错误 xff0c 还请多
  • 笔记(STM32篇)day13——USART串口与PC通信实例

    USART 常用来实现控制器与电脑之间的数据传输 这使得我们调试程序非常方便 xff0c 比如我们可以把一些变量的值 函数的返回值 寄存器标志位等等通过 USART 发送到串口调试助手 xff0c 这样我们可以非常清楚程序的运行状态 xff
  • Leetcode 566. 重塑矩阵(C++矩阵容器)

    题目 输入 xff1a mat 61 1 2 3 4 r 61 1 c 61 4 输出 xff1a 1 2 3 4 思路 将原二维数组变成一维数组 xff0c 在重新放入变换后的二维数组 可以使用一维数组过渡 xff0c 也可以直接用整数除
  • 笔记(嵌入式Linux C篇)4——创建顺序存储表(二级指针方法)

    顺序存储表 概念等同于一个数组 xff0c 使用结构体定义 xff0c 成员为一个某类型的数组 xff0c 以及一个整形的last xff0c 作用是指示顺序存储表最后一个元素的下标 xff0c last默认为 1即数组为空 typedef
  • 笔记(嵌入式Linux C篇)5——单链表(有头节点)

    链表 数据元素随机存储 xff0c 通过指针表示数据之间的逻辑关系的结构就是链式存储结构 xff0c 即链表 一个链表节点包括一个数据域和一个指针域 数据域存储数据 xff0c 指针域存储下一个节点的地址 链表的结构体声明如下 xff1a
  • 实现对单链表的赋值、去重、拆分、排序。

    在一个带头结点的单链表A中 xff0c 自行输入A中的元素值 xff0c 请实现 xff1a xff08 1 xff09 将链表A中值相同的结点 xff0c 仅保留第一次出现的结点 xff1b xff08 2 xff09 将新得到的A链表
  • Linux高级编程——网络通信实现TCP(1)

    基于TCP协议的文件传输 xff08 套接字 xff09 实例 xff1a 客户端 xff1a 只用于收文件 xff1b 执行命令 xff1a 执行文件名 IP Port span class token comment 客户端 输入 执行