【小沐学C++】libcurl实现HTTP/HTTPS请求

文章目录

  • 1、简介
  • 2、下载和编译
    • 2.1 下载
    • 2.2 编译
    • 2.3 使用
  • 3、命令行测试
    • 3.1 获取文件头Headers
    • 3.2 请求内容Request Content
    • 3.3 响应内容Response Content
    • 3.4 GET请求
    • 3.5 POST请求
    • 3.6 其他
  • 4、代码测试
    • 3.1 simple.c
    • 3.2 url2file.c
    • 3.3 simplepost.c
    • 3.4 resolve.c
    • 3.5 progressfunc.c
    • 3.6 http-post.c
    • 3.7 https.c
    • 3.8 httpcustomheader.c
    • 3.9 getinfo.c
    • 3.10 getredirect.c
    • 3.11 getreferrer.c
    • 3.12 执行HTTP的GET请求
    • 3.13 执行HTTP的POST请求
    • 3.14 获取HTTP报头提取Cookie信息
    • 3.15 复杂示例
  • 结语

1、简介

https://github.com/curl/curl
https://curl.se/libcurl/
https://curl.se/download.html

libcurl 是一个免费且易于使用的客户端 URL 传输 库,支持DICT,FILE,FTP,FTPS,GOPHER,GOPHERS,HTTP,HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POPP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMB、SMBS、SMTP、SMTPS、TELNET 和 TFTP。libcurl 支持 SSL 证书,HTTP POST,HTTP PUT,FTP 上传,基于 HTTP 表单的上传, 代理、HTTP/2、HTTP/3、cookie、用户+密码身份验证(基本、 摘要,NTLM,协商,Kerberos),文件传输恢复,http代理 隧道等等!

libcurl 是高度可移植的,它可以在众多 平台,包括 Solaris、NetBSD、FreeBSD、OpenBSD、Darwin、HPUX、IRIX、 AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOs, Mac OS X, Ultrix,QNX,OpenVMS,RISC OS,Novell NetWare,DOS等等…

在这里插入图片描述

2、下载和编译

2.1 下载

官网下载地址:
https://curl.se/download.html

  • curl executable
    您将从此链接获得预构建的“curl”二进制文件(或者在某些情况下,使用此链接带您访问的页面上提供的信息)。您可能会也可能不会将“libcurl”安装为共享库/ DLL。
  • libcurl development
    这是用于 libcurl 开发的 - 但并不总是包含 libcurl 本身。很可能是头文件和文档。如果你打算编译或构建使用 libcurl 的东西,这很可能是你想要的包。
  • libcurl
    这是一个纯二进制 libcurl 包,可能包括头文件和文档,但没有命令行工具和其他问题。如果你想让一个使用 libcurl 的程序使用 libcurl,这很可能是你想要的包。
  • source code
    -您不会从此链接下载预构建的二进制文件。相反,您将获得一个指向带有 curl 源的网站的链接,该链接已针对您的平台进行了调整。您需要设置编译器并努力工作才能从源包构建 curl。

最新源码如下图:
在这里插入图片描述

2.2 编译

解压源码压缩包如下:
在这里插入图片描述
找到windows代码工程文件,如下:在这里插入图片描述
使用vs2017打开如下:
在这里插入图片描述
编译后生成文件如下:
在这里插入图片描述

2.3 使用

使用步骤:

  1. 调用curl_global_init()初始化libcurl
  2. 调用curl_easy_init()函数得到 easy interface型指针
  3. 调用curl_easy_setopt()设置传输选项
  4. 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务
  5. 调用curl_easy_perform()函数完成传输任务
  6. 调用curl_easy_getinfo()接口获取网络请求响应信息,
  7. 调用curl_easy_cleanup()释放内存
  8. 调用curl_global_cleanup()析构libcurl

3、命令行测试

https://curl.se/docs/manual.html

3.1 获取文件头Headers

-H/--header     LINE        (H) # 添加请求头, 可添加多个 -H 参数, 
                                # 参数格式: -H "NAME: VALUE"
 
-A/--user-agen  STRING      (H) # 请求头的 User-Agent 字段
-e/--referer    URL         (H) # 请求头的 Referer 字段
-r/--range      RANGE       (H) # 请求头的 Range 字段
-b/--cookie     STRING/FILE (H) # 请求头的 Cookie 字段, 以字符串的形式提供, 
                                # 或从指定 cookie 文件中读取
 
-c/--cookie-jar     FILE    (H) # 把响应头中的 cookie 保存到指定文件
 
-D/--dump-header    FILE        # 把 headers 信息保存指定文件
-I/--head                       # 只显示文档信息(只显示响应头)

3.2 请求内容Request Content

# 执行命令, 如果是 HTTP 则是请求方法, 如: GET, POST, PUT, DELETE 等
#          如果是 FTP 则是执行 FTP协议命令
-X/--request    COMMAND
 
# HTTP POST 请求内容(并自动发出 POST 请求), 例如: aa=bb&cc=dd
-d/--data       DATA    (H)
 
# HTTP multipart POST 表单数据,(并自动发出 POST 请求)
# 多个表单字段可添加多个 -H 参数, 如果是文件参数, 路径值前面需要加@
# 参考格式: -F "name1=@/filepath" -F "name2=stringvalue"
-F/--form       CONTENT (H)  

3.3 响应内容Response Content

-o/--output FILE    FILE        # 把响应内容输出到指定文件
-O/--remote-name                # 以 URL 的文件名作为文件名称保存响应内容到当前目录
-C/--continue-at    OFFSET      # 断点续传, 从 offset 位置继续传输

3.4 GET请求

curl https://www.baidu.com/         # GET请求, 输出 响应内容
curl -I https://www.baidu.com/      # GET请求, 只输出 响应头
curl -i https://www.baidu.com/      # GET请求, 输出 响应头、响应内容
curl -v https://www.baidu.com/      # GET请求, 输出 通讯过程、头部信息、响应内容等

下载文件
# 指定保存的文件名称下载文件
curl https://www.baidu.com -o baidu.txt
 
# 使用 URL 指定的资源文件名保存下载文件(URL 必须指向具体的文件名)
curl https://www.baidu.com/index.html -O
 
# 指定 Usaer-Agent 和 Referer 请求头的值, 下载文件
curl -A "Mozilla/5.0 Chrome/70.0.3538.110 Safari/537.36" \
     -e "https://www.baidu.com/" \
     https://www.baidu.com/index.html -O

curl -o thatpage.html http://www.example.com/
curl -O http://www.example.com/index.html
curl -O www.haxx.se/index.html -O curl.se/download.html

# 指定Authorization请求头的值, 下载文件
# 参数格式: -H "NAME: VALUE"
curl -H "Authorization: a112121dada" \
     https://www.baidu.com/index.html -O

在这里插入图片描述

3.5 POST请求

 POST 提交 JSON 数据(\表示命令语句还未结束, 换行继续)
curl -H "Content-Type: application/json"                \
     -d '{"username":"hello", "password":"123456"}'     \
     http://localhost/login
 
# POST 提交 表单数据
curl -F "username=hello"                \
     -F "password=123456"               \
     -F "head_image=@filepath.jpg"      \
     http://localhost/register

curl -d "name=Rafael%20Sagula&phone=3320780" http://www.where.com/guest.cgi
curl --data-urlencode "name=Rafael Sagula&phone=3320780" http://www.where.com/guest.cgi
curl -d "user=foobar&pass=12345&id=blablabla&ding=submit" http://www.formpost.com/getthis/post.cgi
curl -F "coolfiles=@fil1.gif;type=image/gif,fil2.txt,fil3.html" http://www.post.com/postit.cgi

3.6 其他

-h/--help                       # 打印帮助信息
-V/--version                    # 显示版本信息
-s/--silent                     # 静默模式, 不输出任何内容
-i/--include                    # 输出包含 headers 信息
-v/--verbose                    # 输出详细内容
-#/--progress-bar               # 以进度条方式显示传输过程

-y/--speed-time     SECONDS     # 连接 超时时间, 单位: 秒,  默认为 30
-m/--max-time       SECONDS     # 读取 超时时间, 必须在该时间内传输完数据, 单位: 秒
--limit-rate        RATE        # 限速传输, 单位: Byte/s
 
-x/--proxy          [PROTOCOL://]HOST[:PORT]    # 设置代理
-U/--proxy-user     USER[:PASSWORD]             # 代理的用户名和密码
-u/--user           USER[:PASSWORD][;OPTIONS]   # 设置服务器的用户密码和登录选项
--cacert            FILE                  (SSL) # 使用指定的 CA 证书
 
-P/--ftp-port       ADR (F) # 指定 FTP 传输的端口
-T/--upload-file    FILE    # 上传文件到指定的 URL (http/ftp) 位置, 
                            # 参考格式: -T "file1" 或 -T "{file1,file2}"
 
-Q/--quote    CMD  (F/SFTP) # 执行命令, -X 只执行一条命令, -Q 可执行多条,
                            # 多条命令将按顺序执行,
                            # 参考格式: -Q "cmd1" -Q "cmd2"

在这里插入图片描述

4、代码测试

打开源码的文件夹的测试示例子文件夹如下:
在这里插入图片描述

3.1 simple.c

/* <DESC>
 * Download a given URL into a local file named page.out.
 * </DESC>
 */
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <curl/curl.h>
#pragma comment(lib, "libcurld.lib")

int main(void)
{
	CURL *curl;
	CURLcode res;

	curl = curl_easy_init();
	if (curl) {
		curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/todos/2");
		/* example.com is redirected, so we tell libcurl to follow redirection */
		curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

		/* Perform the request, res will get the return code */
		res = curl_easy_perform(curl);
		/* Check for errors */
		if (res != CURLE_OK)
			fprintf(stderr, "curl_easy_perform() failed: %s\n",
				curl_easy_strerror(res));

		/* always cleanup */
		curl_easy_cleanup(curl);
	}
	return 0;
}

在这里插入图片描述

3.2 url2file.c

#include "pch.h"
#include <iostream>

/* <DESC>
 * Download a given URL into a local file named page.out.
 * </DESC>
 */
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <curl/curl.h>
#pragma comment(lib, "libcurld.lib")

static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
	size_t written = fwrite(ptr, size, nmemb, (FILE *)stream);
	return written;
}

int main(int argc, char *argv[])
{
	CURL *curl_handle;
	static const char *pagefilename = "test.jpg";
	FILE *pagefile;

	if (argc < 2) {
		printf("Usage: %s <URL>\n", argv[0]);
		return 1;
	}

	curl_global_init(CURL_GLOBAL_ALL);

	/* init the curl session */
	curl_handle = curl_easy_init();

	/* set URL to get here */
	curl_easy_setopt(curl_handle, CURLOPT_URL, argv[1]);

	/* Switch on full protocol/debug output while testing */
	curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);

	/* disable progress meter, set to 0L to enable it */
	curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);

	/* send all data to this function  */
	curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);

	/* open the file */
	pagefile = fopen(pagefilename, "wb");
	if (pagefile) {

		/* write the page body to this file handle */
		curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, pagefile);

		/* get it! */
		curl_easy_perform(curl_handle);

		/* close the header file */
		fclose(pagefile);
	}

	/* cleanup curl stuff */
	curl_easy_cleanup(curl_handle);

	curl_global_cleanup();

	return 0;
}

编译如下:
在这里插入图片描述

运行如下:
在这里插入图片描述
下载图片如下:
在这里插入图片描述

3.3 simplepost.c

/* <DESC>
 * Very simple HTTP POST
 * </DESC>
 */
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;
  CURLcode res;

  static const char *postthis = "moo mooo moo moo";

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);

    /* if we do not provide POSTFIELDSIZE, libcurl will strlen() by
       itself */
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis));

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  return 0;
}

3.4 resolve.c

/* <DESC>
 * Use CURLOPT_RESOLVE to feed custom IP addresses for given host name + port
 * number combinations.
 * </DESC>
 */
#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;
  CURLcode res = CURLE_OK;

  /* Each single name resolve string should be written using the format
     HOST:PORT:ADDRESS where HOST is the name libcurl will try to resolve,
     PORT is the port number of the service where libcurl wants to connect to
     the HOST and ADDRESS is the numerical IP address
   */
  struct curl_slist *host = curl_slist_append(NULL,
                                              "example.com:443:127.0.0.1");

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
    res = curl_easy_perform(curl);

    /* always cleanup */
    curl_easy_cleanup(curl);
  }

  curl_slist_free_all(host);

  return (int)res;
}

3.5 progressfunc.c

/* <DESC>
 * Use the progress callbacks, old and/or new one depending on available
 * libcurl version.
 * </DESC>
 */
#include <stdio.h>
#include <curl/curl.h>

#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL     3000000
#define STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES         6000

struct myprogress {
  curl_off_t lastruntime; /* type depends on version, see above */
  CURL *curl;
};

/* this is how the CURLOPT_XFERINFOFUNCTION callback works */
static int xferinfo(void *p,
                    curl_off_t dltotal, curl_off_t dlnow,
                    curl_off_t ultotal, curl_off_t ulnow)
{
  struct myprogress *myp = (struct myprogress *)p;
  CURL *curl = myp->curl;
  curl_off_t curtime = 0;

  curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime);

  /* under certain circumstances it may be desirable for certain functionality
     to only run every N seconds, in order to do this the transaction time can
     be used */
  if((curtime - myp->lastruntime) >= MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL) {
    myp->lastruntime = curtime;
    fprintf(stderr, "TOTAL TIME: %lu.%06lu\r\n",
            (unsigned long)(curtime / 1000000),
            (unsigned long)(curtime % 1000000));
  }

  fprintf(stderr, "UP: %lu of %lu  DOWN: %lu of %lu\r\n",
          (unsigned long)ulnow, (unsigned long)ultotal,
          (unsigned long)dlnow, (unsigned long)dltotal);

  if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES)
    return 1;
  return 0;
}

int main(void)
{
  CURL *curl;
  CURLcode res = CURLE_OK;
  struct myprogress prog;

  curl = curl_easy_init();
  if(curl) {
    prog.lastruntime = 0;
    prog.curl = curl;

    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");

    curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);
    /* pass the struct pointer into the xferinfo function */
    curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog);

    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
    res = curl_easy_perform(curl);

    if(res != CURLE_OK)
      fprintf(stderr, "%s\n", curl_easy_strerror(res));

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  return (int)res;
}

3.6 http-post.c

/* <DESC>
 * simple HTTP POST using the easy interface
 * </DESC>
 */
#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;
  CURLcode res;

  /* In windows, this will init the winsock stuff */
  curl_global_init(CURL_GLOBAL_ALL);

  /* get a curl handle */
  curl = curl_easy_init();
  if(curl) {
    /* First set the URL that is about to receive our POST. This URL can
       just as well be an https:// URL if that is what should receive the
       data. */
    curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
    /* Now specify the POST data */
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  curl_global_cleanup();
  return 0;
}

3.7 https.c

/* <DESC>
 * Simple HTTPS GET
 * </DESC>
 */
#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;
  CURLcode res;

  curl_global_init(CURL_GLOBAL_DEFAULT);

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");

#ifdef SKIP_PEER_VERIFICATION
    /*
     * If you want to connect to a site who is not using a certificate that is
     * signed by one of the certs in the CA bundle you have, you can skip the
     * verification of the server's certificate. This makes the connection
     * A LOT LESS SECURE.
     *
     * If you have a CA cert for the server stored someplace else than in the
     * default bundle, then the CURLOPT_CAPATH option might come handy for
     * you.
     */
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif

#ifdef SKIP_HOSTNAME_VERIFICATION
    /*
     * If the site you are connecting to uses a different host name that what
     * they have mentioned in their server certificate's commonName (or
     * subjectAltName) fields, libcurl will refuse to connect. You can skip
     * this check, but this will make the connection less secure.
     */
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
#endif

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */
    curl_easy_cleanup(curl);
  }

  curl_global_cleanup();

  return 0;
}

3.8 httpcustomheader.c

/* <DESC>
 * HTTP request with custom modified, removed and added headers
 * </DESC>
 */
#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;
  CURLcode res;

  curl = curl_easy_init();
  if(curl) {
    struct curl_slist *chunk = NULL;

    /* Remove a header curl would otherwise add by itself */
    chunk = curl_slist_append(chunk, "Accept:");

    /* Add a custom header */
    chunk = curl_slist_append(chunk, "Another: yes");

    /* Modify a header curl otherwise adds differently */
    chunk = curl_slist_append(chunk, "Host: example.com");

    /* Add a header with "blank" contents to the right of the colon. Note that
       we are then using a semicolon in the string we pass to curl! */
    chunk = curl_slist_append(chunk, "X-silly-header;");

    /* set our custom set of headers */
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);

    curl_easy_setopt(curl, CURLOPT_URL, "localhost");
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    /* always cleanup */
    curl_easy_cleanup(curl);

    /* free the custom headers */
    curl_slist_free_all(chunk);
  }
  return 0;
}

3.9 getinfo.c

/* <DESC>
 * Use getinfo to get content-type after completed transfer.
 * </DESC>
 */
#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;
  CURLcode res;

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "https://api.thecatapi.com/v1/images/search?limit=1");
    res = curl_easy_perform(curl);

    if(CURLE_OK == res) {
      char *ct;
      /* ask for the content-type */
      res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);

      if((CURLE_OK == res) && ct)
        printf("We received Content-Type: %s\n", ct);
    }

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  return 0;
}

在这里插入图片描述

3.10 getredirect.c

/* <DESC>
 * Show how to extract Location: header and URL to redirect to.
 * </DESC>
 */
#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;
  CURLcode res;
  char *location;
  long response_code;

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");

    /* example.com is redirected, figure out the redirection! */

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));
    else {
      res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
      if((res == CURLE_OK) &&
         ((response_code / 100) != 3)) {
        /* a redirect implies a 3xx response code */
        fprintf(stderr, "Not a redirect.\n");
      }
      else {
        res = curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &location);

        if((res == CURLE_OK) && location) {
          /* This is the new absolute URL that you could redirect to, even if
           * the Location: response header may have been a relative URL. */
          printf("Redirected to: %s\n", location);
        }
      }
    }

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  return 0;
}

3.11 getreferrer.c

/* <DESC>
 * Show how to extract referrer header.
 * </DESC>
 */
#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
  CURL *curl;

  curl = curl_easy_init();
  if(curl) {
    CURLcode res;

    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
    curl_easy_setopt(curl, CURLOPT_REFERER, "https://example.org/referrer");

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));
    else {
      char *hdr;
      res = curl_easy_getinfo(curl, CURLINFO_REFERER, &hdr);
      if((res == CURLE_OK) && hdr)
        printf("Referrer header: %s\n", hdr);
    }

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  return 0;
}

3.12 执行HTTP的GET请求

#include <stdio.h>
#include <curl/curl.h>
#include <string>

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    ((std::string*)userdata)->append(ptr, nmemb);
    return nmemb;
}

int main(void)
{
    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL* curl = curl_easy_init();
    if (curl) 
    {        
        curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com");

        // no certificate, not verify server certificate
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);

        std::string response_data;
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK)
        {
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
        }
        else
        {
            long response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
            printf("response code %d \n", response_code);
            printf("response data : \n ");
            printf(response_data.c_str());
        }

        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();
    return 0;
}

3.13 执行HTTP的POST请求

#include <stdio.h>
#include <curl/curl.h>
#include <string>

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    ((std::string*)userdata)->append(ptr, nmemb);
    return nmemb;
}

int main(int argc, void* argv)
{
    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL* curl = curl_easy_init();
    if (curl)
    {
        // set url
        curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts");

        // no certificate, not verify server certificate
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);

        // set http method
        curl_easy_setopt(curl, CURLOPT_POST, 1);

        // set header
        struct curl_slist * slist = nullptr;
        slist = curl_slist_append(slist, "Content-Type : application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);

        // set body
        std::string body = "{\
            \"title\":\"libcurl post title\",\
            \"body\" : \"libcurl post body\",\
            \"userId\" : 1}";
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());

        // set response callback to read response
        std::string response_data;        
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK)
        {
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
        }
        else
        {
            // get response code
            long response_code;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
            printf("response code %d \n", response_code);
            printf("response data : \n ");
            printf(response_data.c_str());
        }

        curl_slist_free_all(slist);
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();
    return 0;
}

3.14 获取HTTP报头提取Cookie信息

static size_t writeResponse(void *ptr, size_t size, size_t nmemb, void *userData)
{
	std::string* pBuffer = (std::string*)userData;
	size_t length = size * nmemb;
	pBuffer->append((char*)ptr, length);
	return length;
}

int getCookiesData()
{
	CURL *hnd = curl_easy_init();

	curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
	curl_easy_setopt(hnd, CURLOPT_URL, "http://127.0.0.1/login");

	struct curl_slist *headers = NULL;
	headers = curl_slist_append(headers, "cache-control: no-cache");
	headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
	curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
	curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "username=slny001&password=Hx%40kj%2319&loginType=2&undefined=");

	std::string strResponse;
	curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, Writeresponse);//设置回调函数																			//curl_easy_setopt(pCurlHandle, CURLOPT_HEADER, 1);//保存HTTP头部信息到strResponseData
	curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &strResponse);//设置回调函数的参数,获取反馈信息
	curl_easy_setopt(hnd, CURLOPT_HEADERFUNCTION, Writeresponse);//设置回调函数:输出response headers
	string responseHeadBuffer;
	curl_easy_setopt(hnd, CURLOPT_HEADERDATA, &responseHeadBuffer);//设置回调函数参数
	CURLcode ret = curl_easy_perform(hnd);
	if (0 == ret)
	{
		int nPosOfCookie = responseHeadBuffer.find("Cookie: ", 0);
		if (nPosOfCookie > 0)
		{
			int nPosOfEndCookie = responseHeadBuffer.find(";", nPosOfCookie);
			m_cookie = responseHeadBuffer.substr(nPosOfCookie + 7, nPosOfEndCookie - nPosOfCookie - 7);
		}
	}
	curl_slist_free_all(headers);
	curl_easy_cleanup(hnd);
	return 0;
}

3.15 复杂示例

#define CURL_STATICLIB                //如果是静态库方式,需要包含这句

#include "curl\curl.h"
#include <iostream>
#include <list>
#include <string>

#ifdef _DEBUG
#pragma comment(lib,"libcurld.lib")
#else
#pragma comment(lib,"libcurl.lib")
#endif

#pragma comment ( lib, "ws2_32.lib" )
#pragma comment ( lib, "winmm.lib" )
#pragma comment ( lib, "wldap32.lib" )
#pragma comment(lib, "Advapi32.lib")


std::wstring AsciiToUnicode(const std::string& str)
{
    // 预算-缓冲区中宽字节的长度
    int unicodeLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0);
    // 给指向缓冲区的指针变量分配内存
    wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);
    // 开始向缓冲区转换字节
    MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, pUnicode, unicodeLen);
    std::wstring ret_str = pUnicode;
    free(pUnicode);
    return ret_str;
}

std::string UnicodeToUtf8(const std::wstring& wstr)
{
    // 预算-缓冲区中多字节的长度
    int ansiiLen = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
    // 给指向缓冲区的指针变量分配内存
    char *pAssii = (char*)malloc(sizeof(char)*ansiiLen);
    // 开始向缓冲区转换字节
    WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, pAssii, ansiiLen, nullptr, nullptr);
    std::string ret_str = pAssii;
    free(pAssii);
    return ret_str;
}

//ANSI转UTF8
std::string AsciiToUtf8(const std::string& str)
{
    return UnicodeToUtf8(AsciiToUnicode(str));
}

//UTF8转ANSI
std::string Utf8toAscii(const std::string strUTF8)
{
    std::string  strAnsi = "";
    //获取转换为多字节后需要的缓冲区大小,创建多字节缓冲区
    UINT nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8.c_str(), -1, NULL, NULL);
    WCHAR *wszBuffer = new WCHAR[nLen + 1];
    nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8.c_str(), -1, wszBuffer, nLen);
    wszBuffer[nLen] = 0;
    nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, NULL, NULL, NULL, NULL);
    CHAR *szBuffer = new CHAR[nLen + 1];
    nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, szBuffer, nLen, NULL, NULL);
    szBuffer[nLen] = 0;
    strAnsi = szBuffer;
    //清理内存
    delete[]szBuffer;
    delete[]wszBuffer;
    return strAnsi;
}

// reply of the requery
size_t req_reply(void *ptr, size_t size, size_t nmemb, void *stream)
{
    if (stream == NULL || ptr == NULL || size == 0)
        return 0;

    size_t realsize = size * nmemb;
    std::string *buffer = (std::string*)stream;
    if (buffer != NULL)
    {
        buffer->append((const char *)ptr, realsize);
    }
    return realsize;
    /*
    std::string *str = (std::string*)stream;
    (*str).append((char*)ptr, size*nmemb);
    return size * nmemb;
    */
}

/*
功能:get http数据
参数:url:请求字符串。如果请求带参数数据,直接拼凑到url后面;比如:http://127.0.0.1:8080/api/Accounts/Login?uername=admin&password=123
listRequestHeader:请求头数据列表。
bResponseIsWithHeaderData:bool类型,表示响应体中是否包含应答头数据。true,包含,false,不包含。如果包含的话,应答数据中包含Content-Type,Server等信息。
nConnectTimeout:连接超时时间,单位为秒;
nTimeout:读写数据超时时间,单位为秒
返回值:CURLcode
*/
CURLcode curl_get_req(const std::string &url, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10)
{
    // init curl
    CURL *curl = curl_easy_init();
    // res code
    CURLcode res;
    if (curl)
    {
        // set params
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url
        //curl_easy_setopt(m_curl, CURLOPT_PORT, 8089);    //port
        curl_easy_setopt(curl, CURLOPT_POST, 0); // get reqest
        //构建HTTP报文头
        struct curl_slist* headers = NULL;
        if (listRequestHeader.size() > 0)
        {
            std::list<std::string>::iterator iter, iterEnd;
            iter = listRequestHeader.begin();
            iterEnd = listRequestHeader.end();
            for (iter; iter != iterEnd; iter++)
            {
                headers = curl_slist_append(headers, iter->c_str());
            }
            //headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
            //headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
            if (headers != NULL)
            {
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//设置http请求头信息
            }
        }
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
        if (bResponseIsWithHeaderData)
        {
            curl_easy_setopt(curl, CURLOPT_HEADER, 1);//响应体中是否包含了头信息,比如Content-Type:application/json;charset=UTF-8
        }
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout); // set transport and time out time
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout);
        // start request
        res = curl_easy_perform(curl);
        if (headers != NULL)
        {
            curl_slist_free_all(headers); //free the list again
        }
    }
    // release curl
    curl_easy_cleanup(curl);
    return res;
}

CURLcode curl_get_req_ex(CURL *curl, const std::string &url, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10)
{
    // res code
    CURLcode res;
    if (curl)
    {
        // set params
                curl_easy_reset(curl);
        /* enable TCP keep-alive for this transfer */
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
        /* keep-alive idle time to 120 seconds */
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
        /* interval time between keep-alive probes: 30 seconds */
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 30L);

        curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url
        //curl_easy_setopt(m_curl, CURLOPT_PORT, 8089);    //port
        curl_easy_setopt(curl, CURLOPT_POST, 0); // get reqest
        //构建HTTP报文头
        struct curl_slist* headers = NULL;
        if (listRequestHeader.size() > 0)
        {
            std::list<std::string>::iterator iter, iterEnd;
            iter = listRequestHeader.begin();
            iterEnd = listRequestHeader.end();
            for (iter; iter != iterEnd; iter++)
            {
                headers = curl_slist_append(headers, iter->c_str());
            }
            //headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
            //headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
            if (headers != NULL)
            {
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//设置http请求头信息
            }
        }
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
        if (bResponseIsWithHeaderData)
        {
            curl_easy_setopt(curl, CURLOPT_HEADER, 1);//响应体中是否包含了头信息,比如Content-Type:application/json;charset=UTF-8
        }
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout); // set transport and time out time
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout);
        // start request
        res = curl_easy_perform(curl);
        if (headers != NULL)
        {
            curl_slist_free_all(headers); //free the list again
        }
    }
    return res;
}

/*
功能:post http数据
参数:url:请求字符串,比如:http://127.0.0.1:8080/api/Accounts/Login
postParams:请求附带的参数,比如uername=admin&password=123
listRequestHeader:请求头数据列表。
bResponseIsWithHeaderData:bool类型,表示响应体中是否包含应答头数据。true,包含,false,不包含。如果包含的话,应答数据中包含Content-Type,Server等信息。
nConnectTimeout:连接超时时间,单位为秒;
nTimeout:读写数据超时时间,单位为秒
返回值:CURLcode
*/
CURLcode curl_post_req(const std::string &url, const std::string &postParams, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10)
{
    // init curl
    CURL *curl = curl_easy_init();
    // res code
    CURLcode res;
    if (curl)
    {
        // set params
        curl_easy_setopt(curl, CURLOPT_POST, 1); // post req
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url
        //curl_easy_setopt(m_curl, CURLOPT_PORT, 8089);    //port
        curl_easy_setopt(curl, CURLOPT_POST, 1); // post reqest
        //构建HTTP报文头
        struct curl_slist* headers = NULL;
        if (listRequestHeader.size() > 0)
        {
            std::list<std::string>::iterator iter, iterEnd;
            iter = listRequestHeader.begin();
            iterEnd = listRequestHeader.end();
            for (iter; iter != iterEnd; iter++)
            {
                headers = curl_slist_append(headers, iter->c_str());
            }
            //headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
            //headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
            if (headers != NULL)
            {
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//设置http请求头信息
            }
        }
        else
        {
            headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
            if (headers != NULL)
            {
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//设置http请求头信息
            }
        }
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postParams.c_str()); // params
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //返回的头部中有Location(一般直接请求的url没找到),则继续请求Location对应的数据
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
        if (bResponseIsWithHeaderData)
        {
            curl_easy_setopt(curl, CURLOPT_HEADER, 1);//响应体中是否包含了头信息,比如Content-Type:application/json;charset=UTF-8
        }
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout);
        // start request
        res = curl_easy_perform(curl);
        if (headers != NULL)
        {
            curl_slist_free_all(headers); //free the list again
        }
    }
    // release curl
    curl_easy_cleanup(curl);
    return res;
}

CURLcode curl_post_req_ex(CURL *curl, const std::string &url, const std::string &postParams, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10)
{
    // res code
    CURLcode res;
    if (curl)
    {
        // set params
        curl_easy_reset(curl);
        /* enable TCP keep-alive for this transfer */
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
        /* keep-alive idle time to 120 seconds */
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
        /* interval time between keep-alive probes: 30 seconds */
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 30L);

        curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url
        //curl_easy_setopt(m_curl, CURLOPT_PORT, 8089);    //port
        curl_easy_setopt(curl, CURLOPT_POST, 1); // post reqest
        //构建HTTP报文头
        struct curl_slist* headers = NULL;
        if (listRequestHeader.size() > 0)
        {
            std::list<std::string>::iterator iter, iterEnd;
            iter = listRequestHeader.begin();
            iterEnd = listRequestHeader.end();
            for (iter; iter != iterEnd; iter++)
            {
                headers = curl_slist_append(headers, iter->c_str());
            }
            //headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
            //headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded;charset=UTF-8");
            if (headers != NULL)
            {
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//设置http请求头信息
            }
        }
        else
        {
            headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
            if (headers != NULL)
            {
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//设置http请求头信息
            }
        }
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postParams.c_str()); // params
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //返回的头部中有Location(一般直接请求的url没找到),则继续请求Location对应的数据
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
        if (bResponseIsWithHeaderData)
        {
            curl_easy_setopt(curl, CURLOPT_HEADER, 1);//响应体中是否包含了头信息,比如Content-Type:application/json;charset=UTF-8
        }
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout);
        // start request
        res = curl_easy_perform(curl);
        if (headers != NULL)
        {
            curl_slist_free_all(headers); //free the list again
        }
    }
    return res;
}

//实例1
void test1()
{
    curl_global_init(CURL_GLOBAL_ALL);

    //post获取数据
    std::string strResponse = "",strResponseAnsi = "";
    strResponse.clear();
    CURLcode res = curl_post_req("http://127.0.0.1:8080/api/Accounts/Login", "username=admin&password=123", strResponse);
    if (res == CURLE_OK)
    {
        std::string strToken = "";
        strResponseAnsi = Utf8toAscii(strResponse);
    }

    //get获取数据
    strResponse.clear();
    res = curl_get_req("http://127.0.0.1:8080/api/Accounts/Login?username=admin&password=123", strResponse);
    if (res == CURLE_OK)
    {
        int jj = 0;
    }

    curl_global_cleanup();
}

//实例2
void test1()
{
    //post json数据
    CURL * curl = curl_easy_init();
    std::string strResponse = "", strResponseAnsi = "";
    char szRequestUrl[256] = { 0 };
    CURLcode res = CURLE_OK;
    sprintf_s(szRequestUrl, "%s/api/GPS/AddOne", "http://127.0.0.1:8080");
    std::string strPostParams = "";
    try
    {
        boost::property_tree::ptree ptroot;
        ptroot.put("deviceid", "12345678");
        ptroot.put<unsigned int>("deviceStatus", 0);
        ptroot.put<unsigned int>("alarmFlag", 0);
        ptroot.put("lng", fLongitude);
        ptroot.put("lat", fLatitude);
        ptroot.put("speed", 0);
        ptroot.put("direction", 0);
        ptroot.put<int>("altitude", 10);
        ptroot.put("gpsTime", "2018-10-10 12:00:01");
        std::stringstream sstream;
        boost::property_tree::write_json(sstream, ptroot);
        strPostParams = sstream.str();
        bSuccess = true;
    }
    catch (boost::property_tree::ptree_error pt)
    {
        pt.what();
    }
    if (bSuccess)
    {
        std::string strAuthorization = "admin---";
        std::string strRequestHeaders = strAuthorization;
        std::list<std::string> listRequestHeader;
        listRequestHeader.push_back(strRequestHeaders);
        listRequestHeader.push_back("Content-Type:application/json;charset=UTF-8");
        res = curl_post_req_ex(curl, szRequestUrl, strPostParams, strResponse, listRequestHeader);
        if (res == CURLE_OK)
        {
            bSuccess = true;
        }
    }

	curl_easy_cleanup(curl);
}

void main()
{
	test1();
	test2();
}

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/36525.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java语言程序设计试卷6套

目录 Java语言程序设计试卷1 一、单项选择题 二、多项选择题 三、判断题 Java语言程序设计试卷2 一、单项选择题 二、多项选择题 三、判断题 Java语言程序设计试卷3 一、单项选择题 二、多项选择题 三、判断题 Java语言程序设计试卷4 一、单项选择题 二、多项选…

PROFINET转ETHERNET/IP网关西门子通讯协议profinet

大家好&#xff0c;今天我们来聊一款令人兴奋的产品——远创智控YC-PN-EIP&#xff01;它是一款自主研发的 PROFINET 从站功能的通讯网关&#xff0c;可以将 PROFINET网络和ETHERNET/IP 网络连接起来&#xff0c;实现数据传输和交换。但这只是它的基础功能&#xff0c;它还有哪…

HTTP与HTTPS

HTTP与HTTPS介绍 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息&#xff0c;HTTP协议以明文方式发送内容&#xff0c;不提供任何方式的数据加密&#xff0c;如果攻击者截取了Web浏览器和网站服务器之间的传输报文&#xff0c;就可以直接读懂其中的信息&…

【面试题27】Redis中的connect和pconnect如何使用,有什么区别

文章目录 一、背景二、connect函数三、pconnect函数四、区别和使用场景五、总结 一、背景 本文已收录于PHP全栈系列专栏&#xff1a;PHP面试专区。 计划将全覆盖PHP开发领域所有的面试题&#xff0c;对标资深工程师/架构师序列&#xff0c;欢迎大家提前关注锁定。 Redis是一个开…

协议逆向工程(图

协议逆向工程流程图 协议状态机推断的一般示例 状态机方法时间轴

Acwing.859 Kruskal算法求最小生成树(Kruskal算法)

题目 给定一个n个点m条边的无向图&#xff0c;图中可能存在重边和自环&#xff0c;边权可能为负数。 求最小生成树的树边权重之和&#xff0c;如果最小生成树不存在则输出impossible。 给定一张边带权的无向图G(V,E)&#xff0c;其中V表示图中点的集合&#xff0c;E表示图中边…

全网首发,Python解决某象滑动还原验证码100%还原

与一般的滑动验证码不同,某象的滑动还原验证码是将图像上下两块分割,然后在随机一块往右移动,将两块拼图移动成完整的图像才算成功,事实上,解决这类验证码比普通的验证码还要简单 数据集: 我随机采集了某象任意张数据集,将其标注好,top和down代表的是原图中上面还是下面…

嵌入式开发之串口通讯

串口通信(Serial Communication)&#xff0c; 是指外设和计算机间&#xff0c;通过数据信号线 、地线、控制线等&#xff0c;按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少&#xff0c;在远距离通信中可以节约通信成本&#xff0c;但其传输速度比并行传输低&…

前后端实现导出导入功能

目录 导出 1.后端代码 &#xff08;1&#xff09;相关依赖 &#xff08;2&#xff09;自定义实体类 &#xff08;3&#xff09;写一个查询方法list &#xff08;4&#xff09;写导出接口 2.前端代码 3.效果示例 导入 1.后端代码 &#xff08;1&#xff09;写导入接口 …

用 Nginx 禁止国外 IP 访问我的网站...

先来说说为啥要写这篇文章&#xff0c;之前看了下 Nginx 的访问日志&#xff0c;发现每天有好多国外的 IP 地址来访问我的网站&#xff0c;并且访问的内容基本上都是恶意的。因此我决定禁止国外 IP 来访问我的网站。 想要实现这个功能有很多方法&#xff0c;下面我就来介绍基于…

OSPFv2基础03_综合实验

目录 1.创建OSPF进程 2.创建OSPF区域 3.使能OSPF 4.创建虚连接&#xff08;可选&#xff09; 5.OSPF常用命令 6.实验配置步骤 7.实验效果 1.创建OSPF进程 OSPF是一个支持多进程的动态路由协议&#xff0c;OSPF多进程可以在同一台路由器上运行多个不同的OSPF进程&#x…

JDK,JRE,JVM的区别

1.JVM JVM&#xff0c;也叫java虚拟机&#xff0c;用来运行字节码文件&#xff0c;可将字节码翻译为机器码&#xff0c;JVM是实现java跨平台的关键&#xff0c;可以让相同的java代码在不同的操作系统上运行出相同的结果。 2.JRE JRE&#xff0c;也叫java运行时环境&#xff…

医疗金融法律大模型:从ChatDoctor到FinBERT/FinGPT/BloombergGPT、ChatLaw/LawGPT_zh

第一部分 各种医疗类ChatGPT&#xff1a;或中英文数据微调LLaMA、或中文数据微调ChatGLM 1.1 基于LLaMA微调的国内外医疗问答模型 1.1.1 ChatDoctor&#xff1a;通过self-instruct技术提示API的数据和医患对话数据集微调LLaMA Github上有一个基于LLaMA模型的医疗微调模型&am…

MySQL基础篇第3章(基本的SELECT语句)

文章目录 1、SQL概述1.1 SQL背景知识1.2 SQL分类 2、SQL语言的规则与规范2.1 基本规则2.2 SQL大小写规范 &#xff08;建议遵守&#xff09;2.3 注释2.4 命名规则2.5 数据导入指令 3、基本的SELECT语句3.0 SELECT...3.1 SELECT...FROM3.2 列的别名3.3 去除重复行3.4 空置参与运…

【JAVA】这几个JAVA学习网站你绝不能错过(教学课程篇)

个人主页&#xff1a;【&#x1f60a;许思王】 文章目录 前言HOW2J.CNw3cschool菜鸟教程慕课网开课吧黑马程序员B站 前言 JAVA很难学&#xff1f;学不会怎么办&#xff1f;找对学习网站&#xff0c;让你轻松解决困难。 HOW2J.CN HOW2J.CN是我自认为最好的JAVA学习网站&#x…

Docker私有仓库搭建与界面化管理

一、关于Registry 官方的Docker hub是一个用于管理公共镜像的好地方&#xff0c;我们可以在上面找到我们想要的镜像&#xff0c;也可以把我们自己的镜像推送上去。 但是有时候我们的使用场景需要我们拥有一个私有的镜像仓库用于管理我们自己的镜像。这个可以通过开源软件Regi…

5.EFLK(ELK+filebeat)+filter过滤

文章目录 EFLK&#xff08;ELKfilebeat&#xff09;部署filebeat修改配置文件logstash配置 logstash的filter过滤grok(正则捕获插件)内置正则表达式调用自定义表达式 mutate(数据修改插件)重命名字段添加字段删除字段转换数据类型替换字段内容以"|"为分割符拆分数据成…

抖音seo源码部署搭建--代码分享

一、 开发环境搭建 抖音SEO源码部署环境搭建可以分为以下几个步骤&#xff1a; 安装必要的软件和工具&#xff1a;需要安装Node.js、NPM、Git等软件和工具&#xff0c;具体安装方法可以参考官方文档。 下载源码&#xff1a;从GitHub或其他源码托管平台下载抖音SEO源码。 安装…

Failed to start connector [Connector[HTTP/1.1-8080]]

1、解决Web server failed to start. Port 8080 was already in use 2、SpringBoot启动报错:“Error starting ApplicationContext. To display the conditions report re-run your application with ‘debug’ enabled.” 3、Failed to start end point associated with Proto…

Docker部署(1)——将jar包打成docker镜像并启动容器

在代码编写完成即将部署的时候&#xff0c;如果采用docker容器的方法&#xff0c;需要将jar包打成docker镜像并通过镜像将容器启动起来。具体的步骤如下。 一、首先下载java镜像 先使用docker search java命令进行搜索。 然而在拉取镜像的时候要注意不能直接去选择pull java ,…