首先 http2 一定要是加密的,必须要 https 才行,所以第一步要先支持 https 。
如果是一个权威机构认证的证书,那么直接使用正常的请求方式也 OK 的,底层已经处理好了自动可以验证到证书的有效性。然而,如果是我们自己签名的证书底层没有办法自动验证证书,就需要我们自己来解决了。
如果服务器使用的是自签名,libcurl 会报证书无效的错误:
SSL certificate problem: Invalid certificate chain
有两个思路,一是干脆直接不做验证:
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
当然,对于强迫症人群来说,我们怕 DNS 被劫持,所以要自己验证一下证书。当然其实也很简单:
curl_easy_setopt(curl, CURLOPT_CAINFO, "<your certificate path>");
只要证书传对就可以了。如果使用 ip 访问,然而证书中指定了主机名,那么会报错。
WARNING: using IP address, SNI is being disabled by the OS.
这种情况如果一定要使用这个证书并且使用不同域名访问的话,可以把域名验证关掉。
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
https 可以成功了之后,再看如何发出一个 http2 的消息。
起始只要库的版本没问题并且服务器端支持 http2,那么默认的 https 就被底层默认处理为 http2 消息了。当然,显示的设定一下 http 版本算是一种礼貌吧,而且即使设成2.0如果不被支持的话也会默认转为1.1的。
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2);
如果需要使用 http2 的多路传输 pipelining 只需要做一个简单的设置:
curl_multi_setopt(curlm, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
// 尽可能多路复用
curl_easy_setopt(curl, CURLOPT_PIPEWAIT, 1L);
关于更多链接复用和 pipelining 的细节,我还没深入了解,之后有空再研究。
关于环境的搭建:
安装支持 http2 的 apache
mac 系统安装支持 http2 的 curl:
使用 brew 安装一个全新的 curl
brew install curl --with-nghttp2
强行将默认的 curl 连接为这个最新版本
brew link curl —force
然后重启终端就可以生效了。
可以试一试
curl -v --http2 https://10.10.10.109/test_http2.php
参考资料
如果不出意外,那么在返回数据中会有 HTTP/2.0 200
那么就说明环境没问题了。
我们在使用 libcurl 库的时候还要注意一下,一定要连接到新编译出的这个版本,如果是系统默认版本是不支持 http2 的。
我用的方法就是在 cmake 脚本简单指定了一下连接路径:
link_directories(/usr/local/Cellar/curl/7.48.0/lib)
毕竟这不是重点,实现功能最重要。
新的功能已经更新到 github 可以直接 点击前往