使用libcurl库编写HTTP客户端(包括GET/POST/HTTPS)

2023-05-16

最近在写一个应用程序, 需要与HTTP服务器进行数据交互, 于是乎自己写了一个类似wget的功能的客户端, 实现很简单, 但是功能不给力, 只可基本功能. 于是又在网上找了找, 发现使用libcurl库很方便, 很强大, 比起wget之类的, 强大不是一点点. 
下面是常用的GET/POST/HTTPS/多线程HTTPS的使用方法. 仅仅是一个实现函数. 
 
 
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at http://curl.haxx.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/
 
/*
    本文件介绍整curl 库常用的使用方法. 
    包括GET/POST/UPLOAD/HTTPS
                    by xulei 
                2015年3月24日 00:15:20    
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <errno.h>
#include <arpa/inet.h>
#include <curl/curl.h>
#include <semaphore.h> 
#include <stdarg.h>
#include <pthread.h>
#include <signal.h>
#include <time.h>
#include <sys/param.h>
#include <getopt.h>
#include <curl/curl.h>
#include <openssl/crypto.h>
 
 
#define curl_printf printf
 
#define CURL_BUF_MAX_LEN  1024
#define CURL_NAME_MAX_LEN 128
#define CURL_URL_MAX_LEN  128 
 
enum curl_method
{
    CURL_METHOD_GET  = 1,
    CURL_METHOD_POST = 2,
};
 
struct curl_http_args_st
{
    int  curl_method;    // curl 方法命令,enum curl_method
    char url[CURL_URL_MAX_LEN];        // URL 
    
    char file_name[CURL_NAME_MAX_LEN];    // 返回数据保存为文件
    FILE *file_fd;                        // 文件所指向的描述符, 用完后需要手动fclose
 
    int  data_len;                        // 文件数据保存在内存中的长度
    char *data;                            // 文件数据保存在内存中的指针, 用完后手动free 
 
    char post_data[CURL_BUF_MAX_LEN];    // POST 表单数据
    char post_file[CURL_NAME_MAX_LEN];    // POST 文件名
};
 
/* we have this global to let the callback get easy access to it */
static pthread_mutex_t *lockarray;
 
static void lock_callback(int mode, int type, char *file, int line)
{
  (void)file;
  (void)line;
  if (mode & CRYPTO_LOCK) {
    pthread_mutex_lock(&(lockarray[type]));
  }
  else {
    pthread_mutex_unlock(&(lockarray[type]));
  }
}
 
static unsigned long thread_id(void)
{
  unsigned long ret;
 
  ret=(unsigned long)pthread_self();
  return(ret);
}
 
static void init_locks(void)
{
  int i;
 
  lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
                                            sizeof(pthread_mutex_t));
  for (i=0; i<CRYPTO_num_locks(); i++) {
    pthread_mutex_init(&(lockarray[i]),NULL);
  }
 
  CRYPTO_set_id_callback((unsigned long (*)())thread_id);
  CRYPTO_set_locking_callback((void (*)())lock_callback);
}
 
static void kill_locks(void)
{
  int i;
 
  CRYPTO_set_locking_callback(NULL);
  for (i=0; i<CRYPTO_num_locks(); i++)
    pthread_mutex_destroy(&(lockarray[i]));
 
  OPENSSL_free(lockarray);
}
 
 
size_t curl_write_data_cb(void *buffer, size_t size, size_t nmemb, void *stream)
{
    int len = size * nmemb;
    struct curl_http_args_st *args = (struct curl_http_args_st*)stream;    
    
    if (stream)
    {
        if (args->file_name[0])    // 要写文件
        {
            if (!args->file_fd)
            {
                args->file_fd = fopen(args->file_name, "wb");
                if (args->file_fd == NULL)
                {
                    curl_printf("%s[%d]: open file[%s] failed!!\n", __FUNCTION__, __LINE__, args->file_name);
                    return 0;
                }
            }
            fwrite(buffer, size, nmemb, args->file_fd);
        }
        args->data = realloc(args->data, args->data_len + len + 1);    // 多分配一个字节, 以保存\0 
        if (!args->data)
        {
            curl_printf("%s[%d]: realloc failed!!\n", __FUNCTION__, __LINE__);
            return 0;
        }
        memcpy(args->data + args->data_len, buffer, len);
        args->data_len += len;
    }
    
    return len;
}
 
// 创建一个目录,包括其父目录mkdir -p 
int create_dir(const char *sPathName)
{
    char dirname[CURL_NAME_MAX_LEN] = {0};
    int i, len = strlen(sPathName);
    
    strncpy(dirname, sPathName, sizeof(dirname));
 
    len = strlen(dirname);
    for (i = 1; i < len; i++) {
        if (dirname[i] == '/') {
            dirname[i] = 0;
            if (access(dirname, F_OK) != 0) { // 判断是否存在
                if (mkdir(dirname, 0777) == -1) {
                    perror("mkdir  error");
                    curl_printf("mkdir file: dirname=%s\n", dirname);
                    return -1;
                }
            }
            dirname[i] = '/';
        }
    }
 
    return 0;
}
 
/*
    http get func 
*/
int curl_http_get(struct curl_http_args_st *args)
{
    //创建curl对象 
    CURL *curl; 
    CURLcode return_code;
    int ret = -1;
 
    // 如果要保存为文件, 先建立文件目录
    if (args->file_name)
        create_dir(args->file_name);
    
    //curl初始化 
    curl = curl_easy_init(); 
    if (!curl)
    {
        curl_printf("%s[%d]: curl easy init failed\n", __FUNCTION__, __LINE__);
        return ret;;
    }
 
    if (strncmp(args->url, "https://", 8) == 0)
    {
        #if 1    
        // 方法1, 设定为不验证证书和HOST
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        #else
        // 方法2, 设定一个SSL判别证书, 未测试
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1L)
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
        curl_easy_setopt(curl,CURLOPT_CAINFO,"ca-cert.pem");     // TODO: 设置一个证书文件
        #endif 
    }
        
    curl_easy_setopt(curl,CURLOPT_HEADER,0);    //设置httpheader 解析, 不需要将HTTP头写传入回调函数
    
    curl_easy_setopt(curl, CURLOPT_URL,args->url);    //设置远端地址 
 
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);    // TODO: 打开调试信息
    
    curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1);    //设置允许302  跳转
    
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_data_cb);     //执行写入文件流操作 的回调函数
    
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, args);    // 设置回调函数的第4 个参数
    
   <span style="white-space:pre">    </span>curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);    //设置为ipv4类型
    
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);     //设置连接超时,单位s, CURLOPT_CONNECTTIMEOUT_MS 毫秒
 
    // curl_easy_setopt(curl,CURLOPT_TIMEOUT, 5);            // 整个CURL 执行的时间, 单位秒, CURLOPT_TIMEOUT_MS毫秒
    
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);        //linux多线程情况应注意的设置(防止curl被alarm信号干扰)
 
    return_code = curl_easy_perform(curl); 
    if (CURLE_OK != return_code)
    {
        curl_printf("curl_easy_perform() failed: %s\n", curl_easy_strerror(return_code));
        ret  = 0;
    }
 
    if (args->file_fd)        // 若需要再次处理写入的文件, 在此可以直接使用
    { 
        //关闭文件流
        fclose(args->file_fd); 
    } 
    if (args->data)        // 若要对返回的内容进行处理, 可在此处理
    {
        curl_printf("data_len:%d\n%s\n", args->data_len, args->data);
        free(args->data);
        args->data = NULL;
    }
 
    curl_easy_cleanup(curl);
 
    return ret;
}
 
 
/*
    http post func 
*/
int curl_http_post(struct curl_http_args_st *args)
{
    //创建curl对象 
    CURL *curl; 
    CURLcode return_code;
    struct curl_httppost *formpost = NULL;    // POST 需要的参数
    struct curl_httppost *lastptr  = NULL;
    <span style="white-space:pre">    </span>int ret = -1;
    int post_type = 1; // POST 可以有三种方法
 
    // 如果要保存为文件, 先建立文件目录
    if (args->file_name)
        create_dir(args->file_name);
    
    //curl初始化 
    curl = curl_easy_init(); 
    if (!curl)
    {
        curl_printf("%s[%d]: curl easy init failed\n", __FUNCTION__, __LINE__);
        return ret;;
    }
 
    if (strncmp(args->url, "https://", 8) == 0)
    {
        #if 1    
        // 方法1, 设定为不验证证书和HOST
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        #else
        // 方法2, 设定一个SSL判别证书
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
        curl_easy_setopt(curl,CURLOPT_CAINFO,"ca-cert.pem");     // TODO: 设置一个证书文件
        #endif 
    }
        
    curl_easy_setopt(curl,CURLOPT_HEADER,0);    //设置httpheader 解析, 不需要将HTTP头写传入回调函数
    
    curl_easy_setopt(curl, CURLOPT_URL,args->url);    //设置远端地址 
 
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);    // TODO: 打开调试信息
    
    curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1);    //设置允许302  跳转
    
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_data_cb);     //执行写入文件流操作 的回调函数
    
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, args);    // 设置回调函数的第4 个参数
    
    <span style="white-space:pre">    </span>curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);    //设备为ipv4类型
    
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);     //设置连接超时,单位s, CURLOPT_CONNECTTIMEOUT_MS 毫秒
 
    // curl_easy_setopt(curl,CURLOPT_TIMEOUT, 5);            // 整个CURL 执行的时间, 单位秒, CURLOPT_TIMEOUT_MS毫秒
    
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);        //linux多线程情况应注意的设置(防止curl被alarm信号干扰)
 
    if (post_type == 1)
    {
        // 方法1, 普通的POST , application/x-www-form-urlencoded
        curl_easy_setopt(curl,CURLOPT_POST, 1);        // 设置 为POST 方法
        curl_easy_setopt(curl,CURLOPT_POSTFIELDS, args->post_data);        // POST 的数据内容
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(args->post_data));    // POST的数据长度, 可以不要此选项
    }
    else if (post_type == 2)
    {
        //方法2, multipart/formdata请求, POST args->post_data 中的数据, 也可以是将文件内容读取到post_data中        
        curl_formadd(&formpost, &lastptr, CURLFORM_PTRNAME, "reqformat", CURLFORM_PTRCONTENTS, "plain", CURLFORM_END);    // 设置POST 参数
        curl_formadd(&formpost, &lastptr, CURLFORM_PTRNAME, "file", CURLFORM_PTRCONTENTS, args->post_data, CURLFORM_CONTENTSLENGTH, strlen(args->post_data), CURLFORM_END);    
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
    }
    else if (post_type == 3)
    {
        //添加内容Content-Disposition: form-data; name="reqformat"....plain 
        curl_formadd(&formpost, &lastptr, CURLFORM_PTRNAME, "reqformat", CURLFORM_PTRCONTENTS, "plain", CURLFORM_END);// 设置POST 参数
        // 添加上传文件,  Content-Disposition: form-data; name="file"; filename="1.jpg"; filename为默认的名字, content-type 为默认curl识别的
        //curl_formadd(&formpost, &lastptr, CURLFORM_PTRNAME, "file", CURLFORM_FILE, args->post_file, CURLFORM_END);
        // 添加上传文件,  //Content-Disposition: form-data; name="file"; filename="1.jpg".,   filename为指定的名字, content-type 为默认curl识别的
        //curl_formadd(&formpost, &lastptr, CURLFORM_PTRNAME, "file", CURLFORM_FILE, err_file, CURLFORM_FILENAME, "1.jpg", CURLFORM_END); 
        // 添加上传文件,  //Content-Disposition: form-data; name="file"; filename="1.jpg".,   filename为指定的名字, content-type为指定的类型
        curl_formadd(&formpost, &lastptr, CURLFORM_PTRNAME, "file", CURLFORM_FILE, err_file, CURLFORM_FILENAME, "1.jpg", CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END);
 
        // 引用页:  http://blog.csdn.net/zxgfa/article/details/8302059
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
    }
 
    return_code = curl_easy_perform(curl); 
    if (CURLE_OK != return_code)
    {
        curl_printf("curl_easy_perform() failed: %s\n", curl_easy_strerror(return_code));
        ret  = 0;
    }
 
    if (args->file_fd)        // 若需要再次处理写入的文件, 在此可以直接使用
    { 
        //关闭文件流
        fclose(args->file_fd); 
    } 
    if (args->data)        // 若要对返回的内容进行处理, 可在此处理
    {
        curl_printf("data_len:%d\n%s\n", args->data_len, args->data);
        free(args->data);
        args->data = NULL;
    }
 
    curl_easy_cleanup(curl);
    
    if (post_type == 2 || post_type == 3)    // 用这两种方法需要释放POST数据. 
        curl_formfree(formpost);
 
    return ret;
}
 
/*
    1, 从参数中传入操作选项.
    2. 若在线程中要用到HTTPS , 请参看allexamples/threaded-ssl.c 文件使用
*/
int main(int argc, char **argv)
{
    struct curl_http_args_st curl_args;
    memset(&curl_args, 0x00, sizeof(curl_args));
 
    /* Must initialize libcurl before any threads are started */
    curl_global_init(CURL_GLOBAL_ALL);
    /* 多线程使用SSL时, 需要先初始化锁*/
    init_locks();
  
    #if 1 // GET
    curl_args.curl_method = CURL_METHOD_GET;
    //strncpy(curl_args.url, "http://new.baidu.com/index.html", sizeof(curl_args.url)); // http  test ok 
    strncpy(curl_args.url, "http://www.baidu.com/index.html", sizeof(curl_args.url)); // https test ok 
    strncpy(curl_args.file_name, "/tmp/curl/index.html", sizeof(curl_args.file_name));
    #endif 
 
    #if 0 // POST 
    curl_args.curl_method = CURL_METHOD_POST;
    strncpy(curl_args.url, "http://www.wx.com:8080/test.php", sizeof(curl_args.url)); 
    strncpy(curl_args.file_name, "/tmp/curl/index.html", sizeof(curl_args.file_name));
    strncpy(curl_args.post_data, "aa=111111111111111", sizeof(curl_args.post_data)); // 普通post 1 ok 
    // strncpy(curl_args.post_file, "./xx.mp4", sizeof(curl_args.post_file)); // POST 文件OK , 用方法3
    strncpy(curl_args.post_file, "./post_file.txt", sizeof(curl_args.post_file)); // POST 文件OK 
    #endif 
 
    
    switch(curl_args.curl_method)
    {
        case CURL_METHOD_GET:
        {
            curl_http_get(&curl_args);
            break;
        }
        case CURL_METHOD_POST:
        {
            curl_http_post(&curl_args);
            break;
        }
        default:
        {
            curl_printf("curl method error:%d\n", curl_args.curl_method);
            break;
        }
    }
    /* 退出时, 释放锁*/
    kill_locks();
    return 0;
}
 
 

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

使用libcurl库编写HTTP客户端(包括GET/POST/HTTPS) 的相关文章

  • 关于C++ 的无名对象

    include lt iostream gt using namespace std class A public explicit A int val m val val cout lt lt 34 call 1 34 lt lt end
  • pt工具的使用(7) pt-archiver的使用

    一 描述 pt archiver 是归档表的工具 xff0c 在 sql 中写入高效归档和清除作业 目标是在不对 OLTP 查询产生太大影响的情况下 xff0c 将旧数据从表中蚕食掉 xff0c 从而实现低影响 仅向前的作业 您可以将数据插
  • linux-node_exporter突然挂掉(couldn‘t get dbus connection)

    一 背景 突然收到一台机器挂掉的告警 xff0c 去上面查看发现机器正常 xff0c uptime正常 xff0c 没有重启情况 xff0c UID 20029的用户是tidb su tidb的时间较长 xff0c node exporte
  • pt工具的使用(1) pt工具的安装

    PT工具是使用Perl语言编写和执行的 xff0c 所以需要系统中有Perl环境 rpm qa perl DBI perl DBD MySQL perl Time HiRes perl IO Socket SSL 检查是否已经安装pt工具所
  • 使用move_base进行路径规划

    本文所实现的效果来自 ROS入门实例 xff0c 对初学者会有一定帮助 move base是ROS环境下一个重要的功能包 xff0c 可以使机器人在指定框架内移动到目标位置 xff0c 是实现后续导航功能的基础 xff0c 很多人想学习gm
  • iperf3-带宽测试工具的详细使用说明

    软件简介 xff1a iperf3 是一个 TCP UDP 和 SCTP 网络带宽测量工具 是用于主动测量 IP 网络上可达到的最大带宽的工具 它支持调整与时序 xff0c 协议和缓冲区有关的各种参数 对于每个测试 xff0c 它都会报告测
  • 用示波器 查看波特率是多少?

    在做涉及串口操作的应用时 xff0c 要看看串口数据是否正常 xff0c 如果串口通信有问题 xff0c 也可以用示波器来诊断 示波器可以通过高低电平来检测哪里有数据 xff0c 哪里没数据 xff0c 判断哪个模块出问题了 示波器具体用法
  • VS C++ 实现发布订阅模式(Publish/Subscribe)——基于旧版PX4 uORB模式

    源码已经上传至我的 span class token punctuation span Gitee span class token punctuation span span class token punctuation span ht
  • 【TCP专题】TCP连接建立

    今天开始 xff0c 我们整理一些关于TCP协议的知识 这块的内容写起来是非常费劲的 xff0c 因为本身TCP协议就不是一个简单的协议 xff0c 它能获得如今的地位 xff0c 和其复杂且出色的表现是分不开的 什么是面向连接 众所周知
  • cmake中添加引用动态链接和静态链接库

    动态库的添加 xff1a span class hljs keyword link directories span span class hljs envvar PROJECT SOURCE DIR span lib span class
  • ESP32的SDK开发之blufi一键配网

    ESP32 是集成 2 4 GHz Wi Fi 和蓝牙双模的单芯片方案 xff0c 采用台积电 TSMC 超低功耗的 40 纳米工艺 xff0c 拥有最 佳的功耗性能 射频性能 稳定性 通用性和可靠性 xff0c 适用于各种应用和不同功耗需
  • javascript作用域链的灵活运用1

    size 61 large javascript比较出彩的运用之一 xff1a 作用域链 1 对于有洁癖的前台人员来说 xff0c 全局变量就像长在美女脸上的黑斑 xff0c 真的无法容忍 2 javascript权威指南 说的那样 xff
  • ESP32的SDK开发之blufi一键配网微信小程序端开发

    上一篇文章简单介绍了blufi配网协议 xff0c 现在来讲讲再微信小程序端实现配网的控制 xff0c 小程序开发是基于官方原生API开发 本人的微信小程序开发也是初学的 xff0c 由于之前没接触过前端开发 xff0c 软件写的很渣渣 蓝
  • 自定义View之渐变色圆形进度条

    先展示下效果图 xff1a 然后按照自定义view的步骤来实现 我们需要将目标定义清楚 xff1a 目标是渐变色圆形进度条 xff0c 那么 xff0c 使用canvas画弧形是基础了 xff0c 另外是渐变色的效果 xff0c 这里使用L
  • NEMA协议解析 (GPS标准协议)

    概述 NMEA是National Marine Electronics Association 的缩写 xff0c 是美国国家海洋电子协会的简称 xff0c 现在是GPS导航设备统一的RTCM标准协议 协议集合 NMEA 0183协议定义的
  • 深入分析websocket协议,从3个方面设计网络应用层协议丨网络编程|网络IO|epoll|socket|网络协议丨c/c++linux服务器开发

    深入分析websocket协议 xff0c 从3个方面设计网络应用层协议 视频讲解如下 xff1a 深入分析websocket协议 xff0c 从3个方面设计网络应用层协议丨网络编程 网络IO epoll socket 网络协议丨c c 4
  • CMake找不到opencv库解决办法

    一 问题详情 在ubuntu中使用CMake编译链接opencv库的程序时FIND PACKAGE OpenCV REQUIRED 报错 xff0c 找不到opencv xff0c 信息如下 xff1a Found OpenCV Windo
  • 详解使用PHP CURL访问HTTPS

    三年前写过一篇 一个简陋的支持HTTPS的PHP CURL封装函数 xff0c 当时只是知其然不知其所以然 xff0c 今天来详细梳理一下 为方便说明 xff0c 先上代码吧 这是今天重新封装的一个函数 curl POST 64 param
  • adb启动Android系统设置命令

    adb打开系统设置的命令 adb命令打开手机设置页面 设置主页面 adb shell am start com android settings com android settings Settings 安全 adb shell am s
  • bootjar和fw配合动态jar

    Gradle 43 bootJar打包SpringBoot工程并分离jar包和配置文件 ruiurrui的博客 CSDN博客 bootjar Gradle 43 bootJar打包SpringBoot工程并分离jar包和配置文件 ruiur

随机推荐

  • 解决 Ubuntu 无法播放 MP4 格式视频的问题的办法

    解决 Ubuntu22 04 无法播放 MP4 格式视频的问题的办法 问题原因 xff1a 系统中的终端上安装缺少的编解码器 解决办法 xff1a 第一条命令将更新存储库 xff1a sudo apt get update 安装以下包含视频
  • 程序查询方式、程序中断、直接内存存取DMA

    程序查询方式 xff1a 当主机进行I O操作时 xff0c 首先发出询问信号 xff0c 读取设备的状态并根据设备状态决定下一步操作究竟是进行数据传输还是等待 这种控制下 xff0c CPU一旦启动I O xff0c 必须停止现行程序的运
  • app监听白天黑夜

    需要在AndroidManifest中的MainActivity配置 xff1a android configChanges 61 34 uiMode 34 64 param newConfig 64 Override public voi
  • 可缩放性ImageView(可以放大缩小)

    由于项目需求的原因 xff0c 最近一直在研究可缩放性ImageView xff0c 用本文来记录一下最近所学 xff1a 该ImageView的实现功能有 xff1a 1 xff09 初步打开时 xff0c 图片按比例满屏 xff08 填
  • 两行代码用camera2 打开闪光灯

    CameraManager c 61 CameraManager getSystemService Context CAMERA SERVICE c setTorchMode c getCameraList 0 true 打开闪光灯 c s
  • 混淆与加固

    https blog csdn net guolipeng network article details 74551968 上面是混淆 加固方面 腾讯乐固首选 xff0c 阿里加固没毛用 xff0c 360次选 原本大小阿里聚安全腾讯云应
  • C语言10进制转16进制

    void decimal to hexaDecimal int a char strs char hex int i 61 0 int j 61 0 int base 61 16 char tmp 16 while a gt 0 j 61
  • socket网络编程select使用方法

    文章以及源码均为原创 xff0c 当然欢迎转载 xff0c 转载请加说明 server h int select int nfds fd set readfds fd set writefds fd set exceptfds const
  • 海豚蓝牙ASIO软件设置方法

    1 为什么要使用海豚蓝牙音箱 xff0c 能带给我什么样的音乐体验 目前市面上的蓝牙音箱基本上是一个全频段的喇叭来播放CD音质的音乐 xff0c 如果是立体声的是不能通过一个喇叭来播放 xff0c 无法实现空间上的立体效果 xff0c 必须
  • pixhawk学习笔记-----mavlink

    mavlink协议 一帧数据的长度为8到263个字节 其具体的解析如下所示 xff1a 字节的索引 值 含义 0 0xFE V1 0 帧头 xff0c 表示一帧数据的开始 1 0 255 表示有效数据的长度 2 0 255 包序列 xff0
  • Ubuntu搭建本地web站点,并内网穿透实现公网访问

    本次教程我们通过搭建Apache服务 xff0c 部署一个简单的静态样例站点 xff0c 并使用cpolar内网穿透将内网样例站点发布到公网来进行演示 1 设置 Apache Web 服务器 1 1 安装Apache Web span cl
  • 为何某些公司不允许使用 C++ STL?

    最初开始禁用 C 43 43 STL xff0c 更多地是早期项目编码实践中留下的惯例 xff0c 被后来的程序员继承下来 老项目中这种选择尤其地多 不过如果有人将其上升到公司行为在不同项目中全面禁用 STL xff0c 则没有必要 xff
  • 手把手教你无线数传电台透明传输的配置全攻略

    透明传输 功能说明 任意电台发送数据 xff0c 具有相同地址且相同信道的电台均可同时接收数据 数据以透明方式发送和接收 xff0c 所发即所收 电台设置 1 需将 OPTION 特殊功能寄存器的第 7 位配置成 0 xff0c 透明传输模
  • unity寻路插件(A* Pathfinding)小结

    A Pathfinding 详细使用教程 基本功能 1 astarpath cs 核心组件 xff0c 相当于 路 xff0c 场景里应该只存在一个 2 Seeker cs 相当于一个代理 xff0c 寻找路径 xff0c 需要绑定在每一个
  • Socket网络通信C++编程总结

    概述 Socket编程有三种 xff0c 流式套接字 xff08 SOCK STREAM xff09 数据报套接字 SOCK DGRAM 原始套接字 SOCK RAW 前两者较常用 xff0c 这里简单总结前两种编程步骤以及一些参考资料 编
  • 【STM32+cubemx】0029 HAL库开发:HMC5883L磁力计的应用(电子指南针)

    今天我们来学习电子磁力计HMC5883L的使用 先介绍磁力计的基础知识 xff0c 再给一个获取磁力计数据的例子 xff0c 最后讲解HMC5883L磁力计的校准 xff0c 以及一些使用中的经验 1 xff09 HMC5883L磁力计的基
  • stm32F103R6之BKP(备份寄存器)

    目录 概述 侵入检测 RTC校准 概述 Stm32F103有42个16位的备份寄存器 他们处在备份域里 xff0c 当VDD电源被切断 xff0c 他们仍然由VBAT维持供电 当系统在待机模式下被唤醒 xff0c 或系统复位或电源复位时 x
  • Stm32F103R6之控制器局域网

    目录 概述 双CAN bxCAN工作模式 CAN协议特点 xff1a ISO11898标准CAN物理特性 CAN协议帧 概述 bxCAN是基本扩展CAN Basic Extended CAN 的缩写 xff0c 它支持CAN协议2 0A和2
  • 如何输出一个数的二进制数

    实现思想 xff1a 二进制数是以bit为操作数 xff0c 所以要想将一个数转换为二进制数 xff0c 我们需要先要将输入的数字转化为二进制数 xff0c 然后从高位到低位判断每一位是 1 还是 0 xff0c 最后把对应的 1 和 0
  • 使用libcurl库编写HTTP客户端(包括GET/POST/HTTPS)

    最近在写一个应用程序 需要与HTTP服务器进行数据交互 于是乎自己写了一个类似wget的功能的客户端 实现很简单 但是功能不给力 只可基本功能 于是又在网上找了找 发现使用libcurl库很方便 很强大 比起wget之类的 强大不是一点点