C++使用WinHTTP访问http/https服务

环境: window10_x64 & vs2022

python版本: 3.9.13

日常开发中,会遇到c/c++作为客户端访问http/https服务的情况,今天整理下windows10环境下c/c++使用winhttp访问http/https服务的笔记,并提供相关资源下载。

我将从以下几个方面展开:

  • http服务构建
  • https证书生成及服务构建
  • winhttp使用示例
  • 资源下载

一、模拟http服务端

1、构建http服务

这里使用tornado来构建http服务。

示例代码(httpServer1.py):

复制代码
#! /usr/bin/env python3
#-*- coding:utf-8 -*- 
import tornado.ioloop
import tornado.web
import tornado.httpserver
import json,time,datetime
settings = {
    "debug" : False ,    
}
def trace(reqType,reqBody):
    msg = str(datetime.datetime.now()) + " , [" + reqType + "] , " + str(reqBody)
    print(msg)
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        trace("get",self.request.arguments)
        #query = self.get_query_argument("query")
        #print("query : %s" % query)
        self.set_header('content-type', 'application/json')
        #self.write(json.dumps({"result" : "test message"}))
        self.finish(json.dumps({"result" : "get message"}))
    def put(self):
        trace("put",self.request.body)
        self.finish(json.dumps({"result" : "put message"}))

    def post(self):
        #trace("post",self.request.arguments)
        trace("post",self.request.body)
        self.set_header('Content-type', 'application/json')
        #self.set_header('Transfer-Encoding', 'chunked')
        self.finish(json.dumps({"result" : "post message %d" % time.time()}))
if __name__ == "__main__":
    port = 8093
    print("listen on port %d"%port)
    application = tornado.web.Application([
        (r"/.*", MainHandler),
    ],**settings)

    application.listen(port)

    #http_server = tornado.httpserver.HTTPServer(application)
    #http_server.bind(port,"0.0.0.0")
    #http_server.start(num_processes=0) 

    tornado.ioloop.IOLoop.instance().start()

2、服务运行效果

curl测试命令如下:

复制代码
curl -v  http://127.0.0.1:8093 && echo ""

运行效果如下:

二、模拟https服务端

构建https服务,需要使用证书,这里使用自签名证书来实现。

1、生成证书

生成自签名证书(genCertTest1.bat):

复制代码
goto start
cat > openssl.cnf <<EOF
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
C = CN
ST = ShangHai
L = ShangHai
O = MyCompany
OU = Mike_Zhang@live.com
CN = localhost

[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
DNS.2 = 127.0.0.1
IP.1 = 127.0.0.1
EOF
:start

:: 生成包含SAN的证书
openssl req -x509 -newkey rsa:4096  -keyout server.key -out server.crt -days 365 -nodes -config openssl.cnf -extensions v3_req

openssl.cnf文件内容如下:

复制代码
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = CN
ST = ShangHai
L = ShangHai
O = MyCompany
OU = Mike_Zhang@live.com
CN = localhost
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = 127.0.0.1
IP.1 = 127.0.0.1

执行 genCertTest1.bat 脚本,会生产证书文件:

2、构建https服务

这里基于tornado来实现,添加ssl相关内容即可。

示例代码如下(httpsServer1.py):

复制代码
#! /usr/bin/env python3
#-*- coding:utf-8 -*- 
import tornado.ioloop
import tornado.web
import tornado.httpserver
import json,time,datetime
import ssl
settings = {
    "debug" : False ,    
}
def trace(reqType,reqBody):
    msg = str(datetime.datetime.now()) + " , [" + reqType + "] , " + str(reqBody)
    print(msg)
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        trace("get",self.request.arguments)
        #query = self.get_query_argument("query")
        #print("query : %s" % query)
        self.set_header('content-type', 'application/json')
        #self.write(json.dumps({"result" : "test message"}))
        self.finish(json.dumps({"result" : "get message"}))
    def put(self):
        trace("put",self.request.body)
        self.finish(json.dumps({"result" : "put message"}))

    def post(self):
        #trace("post",self.request.arguments)
        trace("post",self.request.body)
        self.set_header('Content-type', 'application/json')
        self.finish(json.dumps({"result" : "post message %d" % time.time()}))
if __name__ == "__main__":
    #ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    ssl_ctx.load_cert_chain(
        certfile="server.crt",  
        keyfile="server.key"    
    )
    ssl_ctx.options |= (
        ssl.OP_NO_SSLv2 | 
        ssl.OP_NO_SSLv3 | 
        ssl.OP_NO_TLSv1 | 
        ssl.OP_NO_TLSv1_1 |
        ssl.OP_NO_COMPRESSION
    )

     # 设置现代加密套件
    ssl_ctx.set_ciphers(
        'ECDHE-ECDSA-AES256-GCM-SHA384:'
        'ECDHE-RSA-AES256-GCM-SHA384:'
        'ECDHE-ECDSA-CHACHA20-POLY1305:'
        'ECDHE-RSA-CHACHA20-POLY1305:'
        'DHE-RSA-AES256-GCM-SHA384'
    )

    # 设置椭圆曲线    
    ssl_ctx.set_ecdh_curve('prime256v1')  # 必需的安全设置

    port = 8443
    print("listen on port %d"%port)
    app = tornado.web.Application([
        (r"/.*", MainHandler),
    ],**settings)


    http_server = tornado.httpserver.HTTPServer(app, ssl_options=ssl_ctx)
    #http_server.listen(port)
    http_server.bind(port,"0.0.0.0")
    http_server.start() 

    tornado.ioloop.IOLoop.current().start()

3、服务运行效果

curl测试命令如下(忽略证书):

复制代码
curl -vk  https://127.0.0.1:8443 && echo ""

运行效果如下:

三、使用WinHTTP实现客户端

1、WinHTTP说明

Microsoft Windows HTTP 服务 (WinHTTP) 提供 HTTP 客户端应用程序编程接口 (API),以便通过 HTTP 协议将请求发送到其他 HTTP 服务器。

该服务提供 C/C++ 应用程序编程接口 (API) ,支持HTTPS协议。

文档地址:

https://learn.microsoft.com/zh-cn/windows/win32/winhttp/winhttp-start-page

c/c++接口文档地址:

https://learn.microsoft.com/zh-cn/windows/win32/winhttp/using-the-winhttp-c-c---api

2、使用示例

关键点:

1)使用 WinHttpConnect 函数创建连接;

2)使用WinHttpOpenRequest设置get/post方法、http/https协议等参数;

3)WinHttpAddRequestHeaders 设置http自定义请求头;

4)WinHttpSendRequest发送数据;

示例代码如下(winhttpTest1.cpp):

完整代码可从如下渠道获取:
关注微信公众号(聊聊博文,文末可扫码)后回复 20250709 获取。
运行效果如下:

四、资源获取

本文涉及资源可从如下渠道获取:
关注微信公众号(聊聊博文,文末可扫码)后回复 20250709 获取。

相关推荐
玖玥拾14 小时前
C/C++ 基础笔记(十四)多态与模板编程
c语言·c++·多态·模板
Roann_seo%15 小时前
C++文件操作完全指南:从文本读写到二进制文件处理
开发语言·c++
坚果派·白晓明16 小时前
【鸿蒙PC】SDL3 适配:AtomCode + Skills 快速集成 NAPI 测试工具
c++·华为·ai编程·harmonyos·atomcode
凡人叶枫16 小时前
Effective C++ 条款17:以独立语句将 newed 对象置入智能指针
java·linux·开发语言·c++·算法
凡人叶枫18 小时前
Effective C++ 条款16:成对使用 new 和 delete 时要采取相同形式
开发语言·c++·effective c++
不吃土豆的马铃薯18 小时前
C++ 高性能网络缓冲区 Buffer 源码解析
linux·服务器·开发语言·网络·c++
.千余18 小时前
【C++】C++继承入门(下):友元、静态成员与菱形继承的底层逻辑
开发语言·c++·笔记·学习·其他
初中就开始混世的大魔王19 小时前
6 Fast DDS-传输层
开发语言·c++·中间件·信息与通信
代码中介商21 小时前
C++ 智能指针完全指南(三):weak_ptr 与循环引用
开发语言·c++
BestOrNothing_201521 小时前
ROS2 C++ 小车控制完整实战(二):自定义 msg 消息发布与订阅保姆级教程
c++·ros2·subscriber·publisher·msg·topic通信·自定义接口