使用C++实现WebSocket服务器是为了解决Web直接访问本地应用程序最佳解决方案。解决云访问硬件最经济的方案或增加了一种解决方法。方案选用开源uWebSockets库。
开发工具选择Visual C++ 2017,所有源码或工程都用它编译或创建。
1. 准备工作
下载以下第三方库最新版源码并且编译供使用。
libuv-1.44.2.zip
openssl_1_1_1s.zip
zlib1213.zip
2. 下载uSocket uWebSocket最新版源码
uSockets-0.8.3.zip
uWebSockets-20.31.0.zip
3. 创建新控制台项目
包含目录添加
d:\sdk\libuv\sdk\include
d:\sdk\zlib\sdk\include
d:\sdk\openssl\sdk\include
库目录添加
d:\sdk\libuv\sdk\lib\Debug
d:\sdk\zlib\sdk\lib\ZlibDllDebug
d:\sdk\openssl\sdk\lib\Debug
在项目属性-配置属性-链接器-输入-附加依赖项
uv.lib
uv_a.lib
zlibwapi.lib
libssl.lib
libcrypto.lib
在项目属性-配置属性-C/C++-语言-C++语言标准-选择ISO C++17标准(/std:c++17)
在项目源码所在目录创建common目录,并且创建uSockets和uWebSockets两个子目录。
将uSockets-0.8.3.zip中的src目录里的所有文件解压到common\uSockets。
将uWebSockets-20.31.0.zip中的src目录里的所有文件解压到common\uWebSockets
4. 编写测试代码
参照uWebSockets例子中的EchoServer代码。
由于我使用的Visual Studio 2017是专业版,不支持EchoServer实例中的代码书写方式。修改如下:
uWS::SocketContextOptions options = { "misc/key.pem", "misc/cert.pem", "1234" };
uWS::SSLApp sslApp = uWS::SSLApp(options);
sslApp.ws<PerSocketData>("/*", {
uWS::CompressOptions(uWS::DEDICATED_COMPRESSOR_4KB | uWS::DEDICATED_DECOMPRESSOR),
100 * 1024 * 1024,
16,
100 * 1024 * 1024,
false,
false,
true,
0,
nullptr,
[](auto */*ws*/) {
/* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */
},
[](auto *ws, std::string_view message, uWS::OpCode opCode) {
ws->send(message, opCode, true);
std::cout << message << std::endl;
},
[](auto */*ws*/) {
/* Check ws->getBufferedAmount() here */
},
[](auto */*ws*/, std::string_view) {
/* Not implemented yet */
},
[](auto */*ws*/, std::string_view) {
/* Not implemented yet */
},
nullptr,
[](auto */*ws*/, int /*code*/, std::string_view /*message*/) {
/* You may access ws->getUserData() here */
}
});
auto h3App = sslApp.listen(9001, [](auto *listen_socket) {
if (listen_socket)
{
std::cout << "Listening on port " << 9001 << std::endl;
}
});
h3App.run();
5. 编译错误处理
找不到头文件
将头文件修改为相对路径访问,例如:
openssl.c文件中#include "libusockets.h"修改为#include "..\libusockets.h"
根据实际目录决定添加..\的个数。
链接函数us_internal_ssl_socket_context_on_server_name失败
添加预定义LIBUS_USE_OPENSSL
这里不要蒙,实际源码已经有这些函数体。但是宏定义给屏蔽了,默认不使用OPENSSL。
将已经废弃的函数修改为对应的安全函数
strcpy -> strcpy_s
sprint->sprint_s
fopen->fopen_s
strdup->_strdup
6.成功编译,执行OK。
注意上面的代码是使用SSL的,但是测试时候使用不带SSL这样测试环境容易建立。
服务器端没有处理编码,在web传送过去的是utf-8。
在此基础上构建自己业务实现自己的硬件监控服务器。