C++ libwebsockets搭建WebSocket服务端及Http客户端、服务端
概念WebRTC浏览器支持情况 WebSocket背景 开源库uWebSockets localhost libWebSockets安装demo测试搭建自己的ws server封装API注册回调协议回调函数参数重要函数说明其他 参考client端html5 搭建Http客户端http post相关知识http client发送post请求概念
WebRTC
WebRTC,名称源自网页即时通信(英语:Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的API。它于6月1日开源并在Google、Mozilla、Opera支持下被纳入万维网联盟的W3C推荐标准。
WebRTC不是html5标准。
WebRTC提供了视频会议的核心技术,包括音视频的采集、编解码、网络传输、显示等功能,并且还支持跨平台:windows,linux,mac,android。
WebSocket是WebRTC的基础,WebSocket为WebRTC负责客服端发现和数据转发。基本上能实现WebSocket,就能实现WebRTC(浏览器支持方面有差异,目前IE10以上浏览器、Opera/Firefox/Chrome支持WebSocket,但各版本IE不支持WebRTC)。
浏览器支持情况
桌上PC端Google Chrome23Mozilla Firefox22Opera18Safari11(仍处于开发者预览阶段)Android端Google Chrome 28(从版本29开始默认开启)Mozilla Firefox 24Opera Mobile 12Google Chrome OSFirefox OSiOS 11Blackberry 10 内置浏览器Bowser
WebSocket
WebSocket是一种在单个TCP连接上进行全双工通信的协议。允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
WebSocket API也被W3C定为标准。
WebSocket 是独立的、创建在 TCP 上的协议。
Websocket 通过HTTP/1.1 协议的101状态码进行握手。
为了创建Websocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)。
背景
现在,很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
而比较新的技术去做轮询的效果是Comet。这种技术虽然可以双向通信,但依然需要反复发出请求。而且在Comet中,普遍采用的长链接,也会消耗服务器资源。
在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
开源库
uWebSockets、Crow、websocketpp、Beast、libwebsockets 、POCO 库的 WebSocket 模块。
uWebSockets
/uNetworking/uWebSockets
uWebSockets,µWS (“microWS”) 是一个客户端和服务器的 WebSocket 和 HTTP 实现。它简单、高效且轻量级。
这个库在底层依赖于 libuv 库 ( libuv是一个高性能的,事件驱动的I/O库,并且提供了跨平台的API。),作为异步网络 I/O 库。
localhost
部分转自/liuruiqun/article/details/45645091
在计算机网络中,localhost 代表了本主机,通过使用localhost可以访问自己主机的网络服务。注意,使用localhost的时候,使用的是回环网络接口,这会绕过本地网络接口硬件,独立于任何网络配置(不受网络防火墙和网卡相关的的限制)。
本地回环地址不属于任何一个有类别地址类,它代表设备的本地虚拟接口。发送到发送到环回地址的任何数据包在 TCP/IP 协议栈的链路层被执行,这些数据包不会交付给任何网络接口控制器(NIC)和设备驱动程序,即数据流不会被发送到一个真正的网络接口。wireshark抓包抓不到。
libWebSockets
uWebSockets是C++17写的,编译器支持不好,而且相关资料太少,改用libWebSockets。libWebSockets是个纯C库,轻量级,同样支持百万级别并发连接。
安装
下载/warmcat/libwebsocketscmake生成vs工程,提示找不到openssl,安装OpenSSL,参考:/yuiiiii/article/details/81297880本来准备编译安装,看了下太麻烦,尝试懒人版安装成功,暂时没发现问题,安装版本为Win64 OpenSSL v1.0.2r,下载连接:/products/Win32OpenSSL.html再次cmake生成vs工程,直接cmd
mkdir buildcd buildcmake .. -G "Visual Studio 15" -DOPENSSL_ROOT_DIR="安装目录\OpenSSL-Win64"
参考:/products/Win32OpenSSL.html
/questions/115684/no-ssl-in-libwebsockets.html?sort=oldest
生成test-client test-server websockets_shared三个项目报错,发现是OPENSSL用的64位的,目标是32位,重新懒人安装32位的再cmake成功。
demo测试
接下来测试自带demo。
在生成的VS目录,test-server项目里,LOCAL_RESOURCE_PATH 定义的资源目录,改为libwebsockets-test-server文件夹的目录,我的是"./…/share/libwebsockets-test-server"。重新编译运行,在浏览器访问http://127.0.0.1:7681,进行demo测试。
搭建自己的ws server
参考:linux下libwebsockets编译及实例:
/yuanwei1314/article/details/76228495
利用libwebsockets写ws、wss服务端和客户端:
/weixin_39510813/article/details/86728804
libwebsockets之简单服务器代码:
/qq_39101111/article/details/79025438
封装
参考:封装利用libwebsockets写出的客户端、服务端程序为客户端服务端类
/weixin_39510813/article/details/86728916
/qq_36972985/article/details/82897868
API
部分转自:
总结使用libwebsockets开发接入层:/qifengzou/article/details/50281545 libwebsockets(三)实现简易websocket服务器:/u013780605/article/details/79489197
相关中文资料很少,感谢博主。结合说明对照自带的demo查看。
注册回调协议
终端向WS服务器发起ws连接请求时,一般会在协议头中通过Sec-WebSockets-Protocol指明协议名。而开源libwebsockets库通过对外提供注册协议回调的接口为用户自定义协议提供服务,注册协议回调的接口中将会指明协议名、以及对应的处理回调、自定义数据的大小等字段。官方demo中有提到第一个protocol必须是http。
/* 注册协议回调配置表 */struct libwebsocket_protocols g_aws_protocols[] ={// 官方demo中有提到第一个protocol必须是http/* first protocol must always be HTTP handler *//*http服务器库中已做实现,直接使用lws_callback_http_dummy即可*/{"http", lws_callback_http_dummy, 0, 0 },{"chat", /* 协议名:其与Sec-Websockets-Protocol字段对应 */aws_callback_im_hdl, /* 回调函数:协议对应的回调处理函数 */sizeof(aws_im_session_data_t), /* 自定义数据空间大小:每个ws连接均会分配一个自定义数据空间 */0,/* max frame size / rx buffer */},{"push", /* 协议名 */aws_callback_push_hdl,/* 回调函数 */sizeof(aws_push_session_data_t),/* 自定义数据空间大小 */0,/* max frame size / rx buffer */},{NULL, NULL, 0, 0 } /* 结束标识 */};
回调函数参数
回调函数用于处理对应协议各阶段的数据:
回调函数参数中的reason指明了调用回调函数的原因,其也代表了ws连接正处于哪个处理阶段或状态。比如:在ws连接创建成功后,应该进行自定义数据的初始化;在ws连接销毁阶段,应该释放自定义数据中用户分配的空间等。因此,要正确的编写协议回调函数就必须对reason各状态值有正确的理解。以下将对服务器端开发者需要关心的reason状态值的进行解释:
LWS_CALLBACK_PROTOCOL_INIT,协议初始化,只调用一次
重要函数说明
其他
使用时发现,单一lws会一直因为原因LWS_CALLBACK_SERVER_WRITEABLE调用回调。
参考
client端html5
/qq_39364032/article/details/79744309?utm_source=blogxgwz0
搭建Http客户端
http post相关知识
即post要在http header中定义编码格式Content-Type,我使用的服务端还需要Content-length等。而这些东西在libwebsockets中需要自己手填。
ref:
四种常见的 POST 提交数据方式:
/softidea/p/5745369.html
Form表单、四种常见的POST请求提交数据方式:
/bigtree_3721/article/details/82809459
http client发送post请求
在libwebsockets的Github中已经有50个例子:
/git/libwebsockets/tree/minimal-examples
但是相关的中文资料太少了,看例子的注释和使用方法也是看得不明不白。
例子中,我有一个minimal-http-client-post.c,内容是发送表单和文件。
在研究了一下一些HTTP基础知识,简化一下这个example,只发送post请求和body内自定义内容,代码如下: