WebSocket服务和客户端测试

一、介绍
  1. C++开发服务端,使用websocketpp库(0.8.2),直接加载头文件即可,下载地址:https://github.com/zaphoyd/websocketpp.git
    • 依赖boost库、openssl库
  2. JavaScript开发客户端
  3. 该测试例子支持websocket ws和websocket wss协议
二、测试代码
  1. server.cpp

    #include <websocketpp/config/asio.hpp>
    #include <websocketpp/server.hpp>
    #include <iostream>typedef websocketpp::server<websocketpp::config::asio> server;
    typedef websocketpp::server<websocketpp::config::asio_tls> server_tls;
    typedef websocketpp::config::asio::message_type::ptr message_ptr;
    typedef websocketpp::lib::shared_ptr<websocketpp::lib::asio::ssl::context> context_ptr;using websocketpp::lib::placeholders::_1;
    using websocketpp::lib::placeholders::_2;
    using websocketpp::lib::bind;void on_message_ws(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {std::cout << "on_message_ws called with hdl: " << hdl.lock().get() << " and message: " << msg->get_payload() << std::endl;try {s->send(hdl, msg->get_payload(), msg->get_opcode());} catch (websocketpp::exception const & e) {std::cout << "Echo failed because: "<< "(" << e.what() << ")" << std::endl;}
    }void on_message_wss(server_tls* s, websocketpp::connection_hdl hdl, message_ptr msg) {std::cout << "on_message_wss called with hdl: " << hdl.lock().get()<< " and message: " << msg->get_payload()<< std::endl;try {s->send(hdl, msg->get_payload(), msg->get_opcode());} catch (websocketpp::exception const & e) {std::cout << "Echo failed because: "<< "(" << e.what() << ")" << std::endl;}
    }
    void on_open_wss(server_tls* s, websocketpp::connection_hdl hdl) {server_tls::connection_ptr con = s->get_con_from_hdl(hdl);std::cout << "on_open_wss client addr:" << con->get_remote_endpoint() << std::endl;
    }
    void on_close_wss(server_tls* s, websocketpp::connection_hdl hdl) {std::cout << "on_close_wss" << std::endl;
    }std::string get_password() {return "test";
    }// See https://wiki.mozilla.org/Security/Server_Side_TLS for more details about
    // the TLS modes. The code below demonstrates how to implement both the modern
    enum tls_mode {MOZILLA_INTERMEDIATE = 1,MOZILLA_MODERN = 2
    };context_ptr on_tls_init(tls_mode mode, websocketpp::connection_hdl hdl) {namespace asio = websocketpp::lib::asio;std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;std::cout << "using TLS mode: " << (mode == MOZILLA_MODERN ? "Mozilla Modern" : "Mozilla Intermediate") << std::endl;context_ptr ctx = websocketpp::lib::make_shared<asio::ssl::context>(asio::ssl::context::sslv23);try {if (mode == MOZILLA_MODERN) {// Modern disables TLSv1ctx->set_options(asio::ssl::context::default_workarounds |asio::ssl::context::no_sslv2 |asio::ssl::context::no_sslv3 |asio::ssl::context::no_tlsv1 |asio::ssl::context::single_dh_use);} else {ctx->set_options(asio::ssl::context::default_workarounds |asio::ssl::context::no_sslv2 |asio::ssl::context::no_sslv3 |asio::ssl::context::single_dh_use);}// ctx->set_password_callback(bind(&get_password));ctx->use_certificate_chain_file("server.pem");ctx->use_private_key_file("server.pem", asio::ssl::context::pem);// Example method of generating this file:// `openssl dhparam -out dh.pem 2048`// Mozilla Intermediate suggests 1024 as the minimum size to use// Mozilla Modern suggests 2048 as the minimum size to use.// ctx->use_tmp_dh_file("dh.pem");std::string ciphers;if (mode == MOZILLA_MODERN) {ciphers = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK";} else {ciphers = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";}if (SSL_CTX_set_cipher_list(ctx->native_handle() , ciphers.c_str()) != 1) {std::cout << "Error setting cipher list" << std::endl;}} catch (std::exception& e) {std::cout << "Exception: " << e.what() << std::endl;}return ctx;
    }int main() {// Create a server endpointserver ws_server;server_tls wss_server;wss_server.set_access_channels(websocketpp::log::alevel::all);wss_server.set_error_channels(websocketpp::log::alevel::all);// Initialize ASIOws_server.init_asio();wss_server.init_asio();// Register our message handlerws_server.set_message_handler(bind(&on_message_ws,&ws_server,::_1,::_2));wss_server.set_message_handler(bind(&on_message_wss,&wss_server,::_1,::_2));wss_server.set_open_handler(bind(&on_open_wss,&wss_server,::_1));wss_server.set_close_handler(bind(&on_close_wss,&wss_server,::_1));wss_server.set_tls_init_handler(bind(&on_tls_init,MOZILLA_INTERMEDIATE,::_1));std::cout << "listen..." << std::endl;// Listen on port 9002ws_server.listen(9002);wss_server.listen(9003);// Start the server accept loopstd::cout << "accept..." << std::endl;ws_server.start_accept();wss_server.start_accept();// Start the ASIO io_service run loopstd::cout << "run..." << std::endl;websocketpp::lib::thread ws_thread(&server::run, &ws_server);websocketpp::lib::thread wss_thread(&server_tls::run, &wss_server);while(1){sleep(1);}std::cout << "run over" << std::endl;
    }
  2. client代码

    1. C++的客户端去websocketpp库中examples找个合适的
    2. 以下是js代码
  • websocket.js

    var ws_socket;
    var wss_socket;function ws_connect() {console.log('WebSocket ws connect...');ws_socket = new WebSocket('ws://hslong.com:9002');// 当WebSocket打开时执行ws_socket.onopen = function(event) {// 发送一个初始化消息console.log('WebSocket ws onopen');};// 当接收到消息时执行ws_socket.onmessage = function(event) {// 打印出服务器返回的数据console.log('WebSocket wss Received: ', event.data);};// 当WebSocket关闭时执行ws_socket.onclose = function(event) {console.log('WebSocket ws connection closed');};// 当有错误发生时执行ws_socket.onerror = function(error) {console.error('WebSocket ws error observed:', error);};
    }
    function ws_disconnect() {console.log('WebSocket ws close...');ws_socket.close();
    }function ws_send() {console.log('WebSocket ws send...');ws_socket.send('Hello, Server!');
    }//wss
    function wss_connect() {console.log('WebSocket wss connect...');wss_socket = new WebSocket('wss://hslong.com:9003');// 当WebSocket打开时执行wss_socket.onopen = function(event) {// 发送一个初始化消息console.log('WebSocket wss onopen');};// 当接收到消息时执行wss_socket.onmessage = function(event) {// 打印出服务器返回的数据console.log('WebSocket wss Received: ', event.data);};// 当WebSocket关闭时执行wss_socket.onclose = function(event) {console.log('WebSocket wss connection closed');};// 当有错误发生时执行wss_socket.onerror = function(error) {console.error('WebSocket wss error observed:', error);};
    }
    function wss_disconnect() {console.log('WebSocket wss close...');wss_socket.close();
    }function wss_send() {console.log('WebSocket wss send...');wss_socket.send('Hello, Server!');
    }
  • index.html

    <!DOCTYPE html>
    <html lang="en">
    <head><title>Websocket Test</title>
    <script>function checkLeave(){disconnect();}
    </script>
    <script src="websocket.js"></script>
    </head>
    <body onbeforeunload="checkLeave()"><p>Websocket Test</p><input id="ws_connect" type="button" value="ws连接" onclick="ws_connect()" /><input id="ws_disconnect " type="button" value="ws断开" onclick="ws_disconnect()" /><input id="ws_send" type="button" value="ws发送" onclick="ws_send()" /><br><br><input id="wss_connect" type="button" value="wss连接" onclick="wss_connect()" /><input id="wss_disconnect " type="button" value="wss断开" onclick="wss_disconnect()" /><input id="wss_send" type="button" value="wss发送" onclick="wss_send()" /></body>
    </html>
三、证书(wss协议使用,不涉及wss协议忽略)
  1. server使用证书
    将server.pem按照代码写的放入运行时对应的目录下

  2. client使用
    将server.crt安装到系统中(win10为例):win+r–>输入:certmgr.msc回车–>受信任的根证书颁发机构–>证书–>右击–>所有任务–>导入server.crt文件

  3. 证书生成

    第1步,生成私钥文件
    openssl genpkey -algorithm RSA -out server.key第2步,生成证书请求文件
    openssl req -new -key server.key -out server.crs第3步,生成证书文件,其中days表示有效天数
    openssl x509 -req -days 36500 -in server.crs -signkey server.key -out server.crt第4步,生成pfx证书,需要设定密码
    openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt第5步,生成pem
    创建server.pem文件,将server.key内容放到开头,将server.crt放到后面server.crs生成输入:Country Name (2 letter code) [AU]:CHState or Province Name (full name) [Some-State]:HeBeiLocality Name (eg, city) []:Sjz  Organization Name (eg, company) [Internet Widgits Pty Ltd]:hslOrganizational Unit Name (eg, section) []:hslCommon Name (e.g. server FQDN or YOUR name) []:hslong.comEmail Address []:hslong@hsl.comPlease enter the following 'extra' attributesto be sent with your certificate requestA challenge password []:hslongAn optional company name []:hslongserver.pfx生成输入密码:hslong
四、运行和配置
  1. 我的测试运行环境

    • server运行在debian11
    • client运行在win10
  2. 本地域名解析

    C盘-->Windows-->System32-->drivers-->etc-->hosts管理员记事本打开-->最后写入 192.168.1.108 hslong.com
    
五、注意事项
  1. Chrome浏览器和Microsoft Edge浏览器ws方式都正常
  2. Chrome浏览器wss方式连接一直失败,不知道哪里限制了
  3. Microsoft Edge浏览器wss方式连接正常,前提条件:(否则不通)
    • new WebSocket(‘wss://hslong.com:9003’); 必须使用证书生成时添加的域名
    • 已经安装证书

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/33408.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解 JavaScript Promise

引言 在当今的 JavaScript 开发中&#xff0c;异步编程已经成为了标准实践。随着我们的应用程序变得越来越复杂&#xff0c;管理异步操作和回调变得尤为关键。在过去&#xff0c;开发者们常常发现自己陷入所谓的“回调地狱”&#xff0c;这是一种由于深层嵌套的回调函数导致的…

三人同行乐享模式:社交电商的新趋势

在数字化时代&#xff0c;社交电商正以其独特的优势崭露头角。其中&#xff0c;“三人同行乐享模式”就是一种创新的购物激励机制&#xff0c;它通过消费者的社交互动和分享&#xff0c;不仅促进了产品的销售&#xff0c;更加强了品牌的推广和影响力。 一、模式简介 此模式的核…

RockChip Android12 Settings二级菜单

一:概述 本文将针对Android12 Settings的二级菜单System进行说明。 二:System 1、Activity packages/apps/Settings/AndroidManifest.xml <activityandroid:name=".Settings$SystemDashboardActivity"android:label="@string/header_category_system&quo…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-30Kaggle竞赛:图片分类

30Kaggle竞赛&#xff1a;图片分类 比赛链接&#xff1a; https://www.kaggle.com/c/classify-leaves 导入包 import torch import torchvision from torch.utils.data import Dataset, DataLoader from torchvision import transforms import numpy as np import pandas as…

【消息队列】六万字长文详细带你RabbitMQ从入门到精通

目录 1、基础篇1.1 为什么要用消息队列MQ1.2 什么是消息队列&#xff1f;1.3 RabbitMQ体系结构介绍1.4 RabbitMQ安装1.5 Hello World1.5.1 目标1.5.2 具体操作 1.6 RabbitMQ用法1.6.1 Work Queues1.6.2 Publish/Subscribe1.6.3 Routing1.6.4 Topics1.6.5 工作模式小结 2. 进阶篇…

推荐三款必备软件,个个五星好评,你一定不要错过

WiseCare365 WiseCare365是一款由WiseCleaner推出的综合性Windows系统优化和加速工具。它集成了多种功能&#xff0c;旨在帮助用户清理、优化和维护电脑系统&#xff0c;提升电脑性能和安全性。 WiseCare365的主要功能包括&#xff1a; 系统清理&#xff1a;它可以清理各种缓存…

Java.io包:从基础到高级的全面指南

Java.io包是Java编程语言中用于处理输入和输出的核心库之一。它提供了一系列类和接口&#xff0c;用于与文件、流、输入输出等进行交互。Java.io的设计目的是为了提供一个简单且一致的API&#xff0c;使得开发者能够轻松地处理各种输入输出操作&#xff0c;无论是文件读写、网络…

CSC公派|哲学老师赴英国红砖大学访学交流

T老师申报CSC公派访问学者&#xff0c;要求世界排名Top200的英国大学。我们在一个月内先后获得了利物浦大学和兰卡斯特大学的邀请函&#xff0c;这两所高校均位列Top200。最终T老师选择英国红砖高校之一的利物浦大学并申报成功顺利出国。 T老师背景&#xff1a; 申请类型&…

AutoTokenizer.from_pretrained报错TypeError: expected string or bytes-like object

问题 tokenizer AutoTokenizer.from_pretrained(distilbert-base-uncased)在用HuggingFace的Transformers加载分词器的时候报错&#xff0c;代码如下: > load tokenizer model distilbert Traceback (most recent call last):File "E:\PythonProjects\Sentiment_Ana…

Vue父组件mounted执行完后再执行子组件mounted

// 创建地图实例 this.map new BMap.Map(‘map’) } } ... 现在这样可能会报错&#xff0c;因为父组件中的 map 还没创建成功。必须确保父组件的 map 创建完成&#xff0c;才能使用 this.$parent.map 的方法。 那么&#xff0c;现在的问题是&#xff1a;如何保证父组件 mo…

端到端的全人体关键点检测:手把手实现从YOLOPose到YOLOWhole

目录 一、搭建yolopose平台二、迁移训练任务2.1 任务拓展数据准备训练模型测试训练模型结论To-do list: 1、数据集,COCO-whole, Halpe;下载好; 2、模型搭建,先基于yolov8来检测人体姿态,17个点; 3、迁移任务,17个点,把它拓展到133个点; 4、优化133个点的模型; 一、搭…

深入理解RLHF技术

在《LLM对齐“3H原则”》这篇文章中&#xff0c;我们介绍了LLM与人类对齐的“3H”原则&#xff0c;但是这些对齐标准主要是基于人类认知进行设计的&#xff0c;具有一定的主观性。因此&#xff0c;直接通过优化目标来建模这些对齐标准较为困难。本文将介绍基于人类反馈的强化学…

ONLYOFFICE 8.1:全面升级,PDF编辑与本地化加强版

目录 &#x1f4d8; 前言 &#x1f4df; 一、什么是 ONLYOFFICE 桌面编辑器&#xff1f; &#x1f4df; 二、ONLYOFFICE 8.1版本新增了那些特别的实用模块&#xff1f; 2.1. 轻松编辑器 PDF 文件 2.2. 用幻灯片版式快速修改幻灯片 2.3. 无缝切换文档编辑、审阅和查…

RS-485和RS-422通信的3.3V低功耗收发器MAX3483

描述 国产MAX3485外观和丝印 该MAX3483ESA为15kV ESD保护、3.3V、低功耗收发器&#xff0c;用于RS-485和RS-422通信。 每个设备包含一个驱动器和一个接收器。 该MAX3483ESA具有压摆率限制驱动器&#xff0c;可最大限度地降低 EMI 并减少因端接不当电缆引起的反射&#xff0c;从…

system verilog 学习1

1 数据类型 sv 引进了一些新的数据类型&#xff0c;它们具有以下优点 &#xff08;1&#xff09;双状态数据类型&#xff1a;更好的性能&#xff0c;更低的内存消耗 &#xff08;2&#xff09;队列、动态和关联数组&#xff1a;减少内存消耗&#xff0c;自带搜索和分类功能 &a…

C# 使用Vector256写了一个简单的帮助类Vector256Helper

当数据量大的时候用普通代码计算非常耗时&#xff0c;这里简单利用simd加速处理 internal unsafe class Vector256Helper{/// <summary>/// 统计元素个数/// </summary>/// <param name"array"></param>/// <param name"elementToCo…

板凳--------57.Linux/Unix 系统编程手册(下) -- SOCKET : Unix domain

https://blog.51cto.com/u_15567199/5204540 【linux网络编程】容错处理文件 wrap.h、wrap.c_wx623c6c9. // 容错处理 wrap.h #ifndef _WRAP_H_ #define _WRAP_H_#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <error.h> #i…

【BSCP系列第2期】XSS攻击的深度剖析和利用(文末送书)

文章目录 前言一、官方地址二、开始&#xff08;15个&#xff09;1&#xff1a;Lab: DOM XSS in document.write sink using source location.search inside a select element2&#xff1a;Lab: DOM XSS in AngularJS expression with angle brackets and double quotes HTML-e…

北邮《计算机网络》MAC子层笔记

文章目录 缩写复习MAC层所在层次动态分配信道算法们的简要介绍信道的五条基本假设多路访问的协议&#xff08;理论上的协议&#xff09;aloha协议CSMA协议其他冲突避免协议无线局域网协议 &#xff0c;MACA 以太网协议802.3&#xff08;实际协议&#xff0c;刚刚是理论&#xf…

小白学python(第一天)

在有了C语言的基础后&#xff0c;我们学python会变得相当容易&#xff0c;毕竟c生万物&#xff0c;废话不多说&#xff0c;直接进入我们的正题 课前准备 Python环境的搭建以及Pycharm的安装 python环境安装 Download Python | Python.org 因为我的电脑是windows&#xff0c;…