江西建设推广网站,苏州 网站的公司,江苏初中课程基地建设网站,wordpress 仿 模板下载基于Crow的C的WebSocket服务器
一、WebSocket
1.1 什么是WebSocket
WebSocket 是一种持久化的通讯协议。 很多网站为了实现推送技术#xff0c;所用的技术都是轮询#xff0c;这种解决方案是指由浏览器每隔一段时间向服务器发出 HTTP 请求#xff0c;然后服务器返回最新的…基于Crow的C的WebSocket服务器
一、WebSocket
1.1 什么是WebSocket
WebSocket 是一种持久化的通讯协议。 很多网站为了实现推送技术所用的技术都是轮询这种解决方案是指由浏览器每隔一段时间向服务器发出 HTTP 请求然后服务器返回最新的数据给客户端。这种模式有很明显的缺点即浏览器需要不断的向服务器发出请求然而 HTTP 请求与响应可能会包含较长的头部其中真正有效的数据可能只是很小的一部分所以这样会消耗很多带宽资源。
WebSocket 是一种网络传输协议其本质是前端与服务器端建立一条TCP长连接服务端可以随时向前端推送数据前端也可以随时向服务端发送数据实现了两者间双向数据实时传输。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455后由 RFC 7936 补充规范。WebSocket 使得客户端和服务器之间的数据交换变得更加简单允许服务端主动向客户端推送数据。在 WebSocket API 中浏览器和服务器只需要完成一次握手两者之间就可以创建持久性的连接并进行双向数据传输。
WebSocket 与 HTTP 对比如下
WebSocket 的优点:
1较少的控制开销在连接创建后服务器和客户端之间交换数据时用于协议控制的数据包头部相对较小2更强的实时性由于协议是全双工的所以服务器可以随时主动给客户端下发数据。相对于 HTTP 请求需要等待客户端发起请求服务端才能响应延迟明显更少3保持连接状态与 HTTP 不同的是WebSocket 需要先创建连接这就使得其成为一种有状态的协议之后通信时可以省略部分状态信息4更好的二进制支持WebSocket 定义了二进制帧相对 HTTP可以更轻松地处理二进制内容5可以支持扩展WebSocket 定义了扩展用户可以扩展协议、实现部分自定义的子协议。
1.2 协议结构
1.2.1 数据帧结构
前面提到的RFC6455中定义了数据帧的格式如下 数据帧的组成结构和其他协议类似都是数据头消息体payload直译为荷载不过WebSocket的数据头长度是可变的受两个因素影响
消息体长度的大小也就是图上的Payload len: 占7或716或764bit。是否有maks key有的话头部多4个字节。
1.2.1 数据帧格式 FIN: 1bit 0 表示不是消息的最后一个分片1 表示是消息的最后一个分片 RSV1, RSV2, RSV3: 各占1bit, 一般情况下全为0, 与Websocket拓展有关, 如果出现非零的值且没有采用WebSocket拓展, 连接出错。 Opcode: 4bit %x0: 表示本次数据传输采用了数据分片, 当前数据帧为其中一个数据分片%x1: 表示这是一个文本帧%x2: 表示这是一个二进制帧%x3-7: 保留的操作代码, 用于后续定义的非控制帧%x8: 表示连接断开%x9: 表示这是一个心跳请求(ping)%xA: 表示这是一个心跳响应(pong)%xB-F: 保留的操作代码, 用于后续定义的非控制帧 Mask: 占1bit 0表示不对数据载荷进行掩码异或操作1表示对数据载荷进行掩码异或操作 Payload len: 占7或716或764bit 0~125: 数据长度等于该值126: 后续的2个字节代表一个16位的无符号整数, 值为数据的长度127: 后续的8个字节代表一个64位的无符号整数, 值为数据的长度 Masking-key: 占0或4bytes;只有客户端给服务器端发送数据时才会有masking key服务器端给客户端发送数据不需要masking key 1: 携带了4字节的Masking-key0: 没有Masking-key payload data: 消息体
1.2.2 掩码算法
结构体中有一个Masking-key这是一个掩码字段它是一个由客户端随机选择的 32 位的值。掩码值必须是不可被预测的。因此掩码必须来自强大的熵源entropy并且给定的掩码不能很容易的预测到后续帧掩码的不可预测性对于预防恶意应用的作者在网上暴露相关的字节数据至关重要。
掩码只影响头的长度不影响消息体对数据进行掩码操作和对数据进行反掩码操作所涉及的步骤是相同的。
掩码、反掩码操作都采用如下算法
j i MOD 4
transformed-octet-i original-octet-i XOR masking-key-octet-j其中
1original-octet-i为原始数据的第 i 字节2transformed-octet-i为转换后的数据的第 i 字节3masking-key-octet-j为 mask key 第 j 字节。
算法是完全公开的运算起来也不复杂。所以数据掩码的作用是增强协议的安全性。而不是为了保护数据本身应该主要还是为了防止早期版本的协议中存在的代理缓存污染攻击等问题。
1.3 与WebSocket类似的协议
1.3.1 AJAX Polling
客户端使用普通的http方式向服务器端请求网页同时执行轮询脚本定期循环的向服务器发送请求例如每5秒发送一次请求获取信息 服务器对每次请求作出响应并返回相应信息就像正常的http请求一样 缺点轮询耗费资源
1.3.2 AJAX Long-Polling
与普通的polling相比区别就是异步等待 客户端使用普通的http方式向服务器端请求网页同时执行轮询脚本向服务器发送数据、请求信息 但是服务器并不是立即就对客户端的请求作出响应而是等待有效的更新 当信息是有效的更新时服务器才会把数据推送给客户端 当客户端接收到服务器的通知时立即会发送一个新的请求进入到下一次的轮询 缺点无更新时发送请求浪费资源
1.3.3 Server Sent Events (SSE) / EventSource:
客户端使用普通的http方式向服务器端请求网页同时网页与服务器之间建立了一个连接 当服务器端有更新时会发送一个事件到客户端 服务器无更新但客户端有请求时仍使用HTTP模式进行请求与应答 优点是如果已有的代码是HTTP请求那么服务器可以不影响现有代码的情况下支持SSE 缺点是半双工客户端无法向服务器发送请求并且部分浏览器不支持。
1.3.4 Comet:
Comet是一种用于web的推送技术能使服务器实时地将更新的信息传送到客户端而无须客户端发出请求目前有两种实现方式长轮询和iframe流。
长轮询 长轮询是在打开一条连接以后保持等待服务器推送来数据再关闭的方式。iframe流 iframe流方式是在页面中插入一个隐藏的iframe利用其src属性在服务器和客户端之间创建一条长链接服务器向iframe传输数据通常是HTML内有负责插入信息的javascript来实时更新页面。 iframe流方式的优点是浏览器兼容好Google公司在一些产品中使用了iframe流如Google Talk。
1.3.5 WebRTC
WebRTC 是一种实时媒体传输技术最初是一个开源项目主要目标是为浏览器和移动应用程序提供建立连接的方法。一个连接是通过指示信号和同步信号建立的这个过程被称为信令。为了在两个设备之间建立 WebRTC 连接需要一个信令服务器。它是一个中间件除了承担建立连接的主要功能外还最大程度上降低了有价值的信息和机密数据泄露的风险。 WebRTC的延迟很低很适合用于大数据量的传输并且因为支持自定义协议所以安全性可控缺点是只有部分浏览器支持以及需要中间件等。
二、CroW
2.1 什么是Crow
Crow是一个用C编写的WebSocket框架旨在提供简单易用的API和高性能。它最初是由Mozilla开发的现在已经成为了一个独立的开源项目。它使用了类似于Python的Flask的路由这使得它易于使用同时其处理速度也很快。
2.2 优点以及缺点
2.2.1 优点
简单易用Crow提供了简单易用的API,可以快速构建WebSocket服务器和客户端应用程序。 高性能Crow使用了Asio库来处理网络I/O操作(旧版使用Boost.asio目前已更新为独立版asio)可以实现高效的并发处理。此外它还支持SSL/TLS加密可以保证通信的安全性和可靠性。 可扩展性Crow提供了插件机制可以方便地扩展其功能。例如可以通过编写自定义插件来实现自定义的消息处理逻辑。 跨平台Crow可以在多种平台上运行包括Windows、Linux和macOS等操作系统。
2.2.2 缺点
文档不够完善Crow的文档很清晰简洁相比于其他一些WebSocket框架来说它的文档还有待进一步完善。 缺乏实时消息队列支持Crow目前还不支持实时消息队列功能如果需要实现类似消息队列的功能需要自己编写相关的代码。 不支持多路复用Crow目前只支持单个TCP连接如果需要同时处理多个客户端请求需要为每个客户端创建一个新的线程或进程。 不支持HTTPS:虽然Crow支持SSL/TLS加密但是不支持HTTPS协议。如果需要通过HTTPS协议进行通信需要自己实现相关的加密算法。 不适合大规模应用由于Crow的设计初衷是用于小型到中型的应用场景因此在面对大规模应用时可能会出现性能瓶颈等问题。
2.3 编译安装
在安装Crow之前需要先安装ASIO要求1.22.0以上的版本
然后下载、MAKE、install
git clone https://github.com/CrowCpp/Crow.git
mkdir build
cd build
cmake .. -DCROW_BUILD_EXAMPLESOFF -DCROW_BUILD_TESTSOFF
make install之后能看到如下目录 其中include里的就是所有的源码平时用的时候只需要包含include/crow.h即可
三、基于Crow的C服务器与客户端示例
3.1 客户端
客户端我是用HTMLJS那一套Crow也可以写C客户端 JS里面使用WebSocket可以直接使用WebSocket对象这个类只有两个函数
var wSocket new WebSocket(ws://localhost:18080/ws);
wSocket.close([code[, reason]]) // 关闭当前链接
wSocket.send(data) // 发送数据写一个html在里面加一个按钮点击然后调用send发送数据即可 具体可参考 https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket
3.2 服务器
先定义Crow::app对象然后绑定ws路由再监听指定端口即可 CROW_WEBSOCKET_ROUTE(app, /ws).onopen([](crow::websocket::connection conn) {CROW_LOG_INFO new websocket connection from conn.get_remote_ip();}).onclose([](crow::websocket::connection conn, const std::string reason) {CROW_LOG_INFO websocket connection closed: reason;}).onmessage([](crow::websocket::connection conn, const std::string data, bool is_binary) {CROW_LOG_INFO Recv message: data;if (is_binary)conn.send_binary(data);elseconn.send_text(data);});app.loglevel(LogLevel::Debug).port(18080).multithreaded().run();3.3 运行测试 还可以使用测试网站http://www.websocket-test.com/ (这个网站是我看到某个文章上推的安全性未知)