首页 > 编程语言 >封装利用libwebsockets写出的客户端、服务端程序为客户端服务端类

封装利用libwebsockets写出的客户端、服务端程序为客户端服务端类

时间:2023-10-11 15:37:55浏览次数:37  
标签:info int lws server ssl client libwebsockets 服务端 客户端

1.封装 我们后续将使用c++来开发程序,因此有必要将用c写成的wss客户端、服务端程序作进一步封装,使其成为wss客户端类和服务端类,这样更便于调用。封装后的程序结构:   ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class$ tree  . ├── client │   ├── client │   ├── compile.sh │   ├── lws_client.cpp │   ├── lws_client.h │   └── test.cpp └── server     ├── compile.sh     ├── lws_server.cpp     ├── lws_server.h     ├── server     └── test.cpp   2 directories, 10 files     2.封装后写wss客户端、服务端 封装后写wss客户端和服务端将非常方便,只需要几行即可创建一个客户端或者服务端:   服务端创建测试程序:   #include "lws_server.h" #include <signal.h>   static int interrupted;   void sigint_handler(int sig) { interrupted = 1; }   int main(int argc,char **argv) {     //接收SIGINT(ctrl+c)信号     signal(SIGINT, sigint_handler);     int n = 0;       //创建服务器对象(可以指定端口,这里指定了8000)     lws_server server(8000);       //初始化服务器     server.init();     lwsl_notice("port:%d\n",server.get_port());       //设置ssl(不使用ssl则传空,使用则传入证书文件路径)     server.set_ssl(NULL,NULL,NULL,0);       //创建服务器     server.create();       //服务器运行(运行时可设置间隔等待时间,这里为1000,单位为ms)     while(n >= 0 && !interrupted)         n = server.run(1000);       //销毁资源     server.destroy();       return 0; }   客户端创建测试程序:   #include "lws_client.h" #include <signal.h>   static int interrupted;   void sigint_handler(int sig) { interrupted = 1; }   int main(int argc,char **argv) {     signal(SIGINT, sigint_handler);     int n = 0;       //创建客户端对象(传入服务器地址和端口)     lws_client client("127.0.0.1",8000);       //初始化客户端     client.init();       //设置ssl     client.set_ssl(NULL,NULL,NULL,0);       //创建客户端     client.create();       //连接服务器(需要ssl连接时传入1,否则传0)     client.connect(0);       //客户端运行     while(n >= 0 && !interrupted)         n = client.run(1000);       //销毁资源     client.destroy();       return 0; }   3.测试结果 运行服务端:   ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class/server$ ./server  [2018/09/12 18:34:56:3472] NOTICE: port:8000 [2018/09/12 18:34:56:3493] NOTICE: Creating Vhost 'default' port 8000, 1 protocols, IPv6 off     运行客户端:   ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class/client$ ./client  [2018/09/12 18:35:43:4919] NOTICE: Creating Vhost 'default' (serving disabled), 1 protocols, IPv6 off [2018/09/12 18:35:43:4947] NOTICE: Connected to server ok! [2018/09/12 18:35:43:4964] NOTICE: Tx: 你好 1 [2018/09/12 18:35:43:4987] NOTICE: Tx: 你好 2 [2018/09/12 18:35:43:4994] NOTICE: Rx: 你好 1 [2018/09/12 18:35:43:4999] NOTICE: Rx: 你好 2 [2018/09/12 18:35:43:5000] NOTICE: Tx: 你好 3 [2018/09/12 18:35:43:5007] NOTICE: Rx: 你好 3     服务端:   ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class/server$ ./server  [2018/09/12 18:34:56:3472] NOTICE: port:8000 [2018/09/12 18:34:56:3493] NOTICE: Creating Vhost 'default' port 8000, 1 protocols, IPv6 off [2018/09/12 18:35:43:4939] NOTICE: Client connect! [2018/09/12 18:35:43:4979] NOTICE: recvied message:你好 1 [2018/09/12 18:35:43:4989] NOTICE: recvied message:你好 2 [2018/09/12 18:35:43:5001] NOTICE: recvied message:你好 3     测试通信成功。目前服务器为回显服务器,其底层采用的poll机制。   4.客户端、服务端类程序 服务端程序类:   #include "lws_server.h"   #define MAX_PAYLOAD_SIZE  (10 * 1024)   static struct lws_context_creation_info ctx_info = { 0 }; static struct lws_context *context = NULL;   /**  * 会话上下文对象,结构根据需要自定义  */ struct session_data {     int msg_count;     unsigned char buf[LWS_PRE + MAX_PAYLOAD_SIZE];     int len;     bool bin;     bool fin; };   /* 构造函数 */ lws_server::lws_server(int listen_port) {     port = listen_port; }   /* 析构函数 */ lws_server::~lws_server() {     lwsl_notice("析构完成\n"); }   /* 拷贝构造 */ lws_server::lws_server(const lws_server &obj) {      }   int lws_server::get_port() {     return port; }   /* 服务器底层实现的回调函数 */ static int protocol_my_callback(struct lws *wsi,                          enum lws_callback_reasons reason,                          void *user,                          void *in,                          size_t len ) {     struct session_data *data = (struct session_data *) user;       switch ( reason ) {         case LWS_CALLBACK_ESTABLISHED:       // 当服务器和客户端完成握手后             lwsl_notice("Client connect!\n");             break;           case LWS_CALLBACK_RECEIVE:           // 当接收到客户端发来的帧以后             // 判断是否最后一帧             data->fin = lws_is_final_fragment( wsi );             // 判断是否二进制消息             data->bin = lws_frame_is_binary( wsi );             // 对服务器的接收端进行流量控制,如果来不及处理,可以控制之             // 下面的调用禁止在此连接上接收数据             lws_rx_flow_control( wsi, 0 );               // 业务处理部分,为了实现Echo服务器,把客户端数据保存起来             memcpy( &data->buf[ LWS_PRE ], in, len );             data->len = len;             lwsl_notice("recvied message:%s\n",&data->buf[ LWS_PRE ]);               // 需要给客户端应答时,触发一次写回调             lws_callback_on_writable( wsi );             data = NULL;             break;           case LWS_CALLBACK_SERVER_WRITEABLE:   // 当此连接可写时             lws_write( wsi, &data->buf[ LWS_PRE ], data->len, LWS_WRITE_TEXT );             // 下面的调用允许在此连接上接收数据             lws_rx_flow_control( wsi, 1 );             break;     }       // 回调函数最终要返回0,否则无法创建服务器     return 0; }   /**  * 支持的WebSocket子协议数组  * 子协议即JavaScript客户端WebSocket(url, protocols)第2参数数组的元素  * 你需要为每种协议提供回调函数  */ struct lws_protocols protocols[] = {     {         //协议名称,协议回调,接收缓冲区大小         "ws", protocol_my_callback, sizeof( struct session_data ), MAX_PAYLOAD_SIZE,     },     {         NULL, NULL,   0 // 最后一个元素固定为此格式     } };   void lws_server::init() {     ctx_info.port = 8000;     ctx_info.iface = NULL; // 在所有网络接口上监听     ctx_info.protocols = protocols;     ctx_info.gid = -1;     ctx_info.uid = -1;     ctx_info.options = LWS_SERVER_OPTION_VALIDATE_UTF8; }   int lws_server::set_ssl(const char* ca_filepath,                              const char* server_cert_filepath,                             const char*server_private_key_filepath,                             bool is_support_ssl) {     if(!is_support_ssl)     {         ctx_info.ssl_ca_filepath = NULL;         ctx_info.ssl_cert_filepath = NULL;         ctx_info.ssl_private_key_filepath = NULL;     }     else     {         ctx_info.ssl_ca_filepath = ca_filepath;         ctx_info.ssl_cert_filepath = server_cert_filepath;         ctx_info.ssl_private_key_filepath = server_private_key_filepath;         ctx_info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;     //ctx_info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;     }       return is_support_ssl; }     int lws_server::create() {     context = lws_create_context(&ctx_info);     if (!context) { lwsl_err("lws_server create failed\n"); return -1; }     return 1; }     int lws_server::run(int wait_time) {     return lws_service(context, wait_time); }   void lws_server::destroy() {     lws_context_destroy(context); }   /******************************************************************************                     版权所有 (C), 2017-2019, ZY    ******************************************************************************   文 件 名   : lws_server.h   版 本 号   : 初稿   作    者   : ZY   生成日期   : 2018年9月12日 星期三   最近修改   :   功能描述   : lws_server.cpp 的头文件   函数列表   :   修改历史   :   1.日    期   : 2018年9月12日 星期三     作    者   : ZY     修改内容   : 创建文件   ******************************************************************************/   /*----------------------------------------------*  * 包含头文件                                   *  *----------------------------------------------*/   /*----------------------------------------------*  * 外部变量说明                                 *  *----------------------------------------------*/   /*----------------------------------------------*  * 外部函数原型说明                             *  *----------------------------------------------*/   /*----------------------------------------------*  * 内部函数原型说明                             *  *----------------------------------------------*/   /*----------------------------------------------*  * 全局变量                                     *  *----------------------------------------------*/   /*----------------------------------------------*  * 模块级变量                                   *  *----------------------------------------------*/   /*----------------------------------------------*  * 常量定义                                     *  *----------------------------------------------*/   /*----------------------------------------------*  * 宏定义                                       *  *----------------------------------------------*/   #ifndef __LWS_SERVER_H__ #define __LWS_SERVER_H__     #ifdef __cplusplus #if __cplusplus extern "C"{ #endif #endif /* __cplusplus */   #include <libwebsockets.h>   class lws_server {     private:         int port;       public:         lws_server(int listen_port);                  ~lws_server();           lws_server(const lws_server &obj);           int get_port();           void init();           int set_ssl(const char* ca_filepath,                              const char* server_cert_filepath,                             const char*server_private_key_filepath,                             bool is_support_ssl);           int create();           int run(int wait_time);           void destroy(); };   #ifdef __cplusplus #if __cplusplus } #endif #endif /* __cplusplus */     #endif /* __LWS_SERVER_H__ */     客户端程序类:   #include "lws_client.h"   #define MAX_PAYLOAD_SIZE  10 * 1024   static struct lws_context_creation_info ctx_info = { 0 }; static struct lws_context *context = NULL; static struct lws_client_connect_info conn_info = { 0 }; static struct lws *wsi = NULL;   /**  * 会话上下文对象,结构根据需要自定义  */ struct session_data {     int msg_count;     unsigned char buf[LWS_PRE + MAX_PAYLOAD_SIZE];     int len; };   /**  * 某个协议下的连接发生事件时,执行的回调函数  *  * wsi:指向WebSocket实例的指针  * reason:导致回调的事件  * user 库为每个WebSocket会话分配的内存空间  * in 某些事件使用此参数,作为传入数据的指针  * len 某些事件使用此参数,说明传入数据的长度  */ int lws_client_callback( struct lws *wsi,                  enum lws_callback_reasons reason,                  void *user,                  void *in,                  size_t len ) {     struct session_data *data = (struct session_data *) user;       switch ( reason ) {           case LWS_CALLBACK_CLIENT_ESTABLISHED:   // 连接到服务器后的回调             lwsl_notice( "Connected to server ok!\n" );             break;           case LWS_CALLBACK_CLIENT_RECEIVE:       // 接收到服务器数据后的回调,数据为in,其长度为len             lwsl_notice( "Rx: %s\n", (char *) in );             break;           case LWS_CALLBACK_CLIENT_WRITEABLE:     // 当此客户端可以发送数据时的回调             if ( data->msg_count < 3 ) {                 // 前面LWS_PRE个字节必须留给LWS                 memset( data->buf, 0, sizeof( data->buf ));                 char *msg = (char *) &data->buf[ LWS_PRE ];                 data->len = sprintf( msg, "你好 %d", ++data->msg_count );                 lwsl_notice( "Tx: %s\n", msg );                 // 通过WebSocket发送文本消息                 lws_write( wsi, &data->buf[ LWS_PRE ], data->len, LWS_WRITE_TEXT );             }             break;           default:             break; //            lwsl_notice("not support\n");     }       return 0; }   /**  * 支持的WebSocket子协议数组  * 子协议即JavaScript客户端WebSocket(url, protocols)第2参数数组的元素  * 你需要为每种协议提供回调函数  */ struct lws_protocols protocols[] = {     {         //协议名称,协议回调,接收缓冲区大小         "ws", lws_client_callback, sizeof( struct session_data ), MAX_PAYLOAD_SIZE,     },     {         NULL, NULL,   0 // 最后一个元素固定为此格式     } };   /* 构造函数 */ lws_client::lws_client(char *_address,int _port) {     server_address = _address;     port = _port; }   /* 析构函数 */ lws_client::~lws_client() {     lwsl_notice("析构完成\n"); }   /* 拷贝构造 */ lws_client::lws_client(const lws_client &obj) {      }   /* 初始化 */ void lws_client::init() {     ctx_info.port = CONTEXT_PORT_NO_LISTEN;     ctx_info.iface = NULL;     ctx_info.protocols = protocols;     ctx_info.gid = -1;     ctx_info.uid = -1; }   /* 设置ssl */ int lws_client::set_ssl(const char* ca_filepath,                              const char* server_cert_filepath,                             const char*server_private_key_filepath,                             bool is_support_ssl) {     if(!is_support_ssl)     {         ctx_info.ssl_ca_filepath = NULL;         ctx_info.ssl_cert_filepath = NULL;         ctx_info.ssl_private_key_filepath = NULL;     }     else     {         ctx_info.ssl_ca_filepath = ca_filepath;         ctx_info.ssl_cert_filepath = server_cert_filepath;         ctx_info.ssl_private_key_filepath = server_private_key_filepath;         ctx_info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;     //ctx_info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;     }       return is_support_ssl; }   /* 创建客户端 */ int lws_client::create() {     // 创建一个WebSocket处理器     context = lws_create_context( &ctx_info );     if(!context)         return -1;     return 0; }   /* 连接客户端 */ int lws_client::connect(int is_ssl_support) {     char addr_port[256] = { 0 };     sprintf(addr_port, "%s:%u", server_address, port & 65535 );       // 客户端连接参数     conn_info = { 0 };     conn_info.context = context;     conn_info.address = server_address;     conn_info.port = port;       if(!is_ssl_support)         conn_info.ssl_connection = 0;     else         conn_info.ssl_connection = 1;     conn_info.path = "./";     conn_info.host = addr_port;     conn_info.origin = addr_port;     conn_info.protocol = protocols[ 0 ].name;       // 下面的调用触发LWS_CALLBACK_PROTOCOL_INIT事件     // 创建一个客户端连接     wsi = lws_client_connect_via_info( &conn_info );     if(!wsi)         return -1;     return 1; }   /* 运行客户端 */ int lws_client::run(int wait_time) {     lws_service( context, wait_time );     /**      * 下面的调用的意义是:当连接可以接受新数据时,触发一次WRITEABLE事件回调      * 当连接正在后台发送数据时,它不能接受新的数据写入请求,所有WRITEABLE事件回调不会执行      */     lws_callback_on_writable( wsi ); }   /* 销毁 */ void lws_client::destroy() {     lws_context_destroy(context); }     /******************************************************************************                     版权所有 (C), 2017-2019, ZY    ******************************************************************************   文 件 名   : lws_client.h   版 本 号   : 初稿   作    者   : ZY   生成日期   : 2018年9月12日 星期三   最近修改   :   功能描述   : lws_client.cpp 的头文件   函数列表   :   修改历史   :   1.日    期   : 2018年9月12日 星期三     作    者   : ZY     修改内容   : 创建文件   ******************************************************************************/   /*----------------------------------------------*  * 包含头文件                                   *  *----------------------------------------------*/   /*----------------------------------------------*  * 外部变量说明                                 *  *----------------------------------------------*/   /*----------------------------------------------*  * 外部函数原型说明                             *  *----------------------------------------------*/   /*----------------------------------------------*  * 内部函数原型说明                             *  *----------------------------------------------*/   /*----------------------------------------------*  * 全局变量                                     *  *----------------------------------------------*/   /*----------------------------------------------*  * 模块级变量                                   *  *----------------------------------------------*/   /*----------------------------------------------*  * 常量定义                                     *  *----------------------------------------------*/   /*----------------------------------------------*  * 宏定义                                       *  *----------------------------------------------*/   #ifndef __LWS_CLIENT_H__ #define __LWS_CLIENT_H__     #ifdef __cplusplus #if __cplusplus extern "C"{ #endif #endif /* __cplusplus */   #include "libwebsockets.h"   class lws_client {     private:           char *server_address;           int port;       public:           lws_client(char *lws_server_address,int port);           ~lws_client();           lws_client(const lws_client &obj);           void init();           int set_ssl(const char* ca_filepath,                              const char* server_cert_filepath,                             const char*server_private_key_filepath,                             bool is_support_ssl);           int create();           int connect(int is_ssl_support);           int run(int wait_time);           void destroy(); };     #ifdef __cplusplus #if __cplusplus } #endif #endif /* __cplusplus */     #endif   

标签:info,int,lws,server,ssl,client,libwebsockets,服务端,客户端
From: https://www.cnblogs.com/kn-zheng/p/17757287.html

相关文章

  • 传奇服务端Mirserver功能讲解
    DBServer(数据库服务端)ConnectionFDB(人物数据库,数据库格式为传奇自定义格式)Log(角色选择服务端日志)AddrTable.txt(IP地址配置)!IdList.txt(缴费账号列表,!Setup.exe中ServiceMode=TRUE时起作用)!ServerInfo.txt(IP地址配置)DBServer.exe(数据库主程序)DBSrc.ini(数据库主程序配......
  • nodejs xxl-job-executor 客户端试用
    代码fork自awesomeoxc/xxl-job-executor-nodejs,进行了一些以来包的升级,同时发布npm包到npm仓库中,方便使用npm包名称npm包我已经发布npm仓库中了,可以直接使用@dalongrong/xxl-job-executor参考使用安装npminstall@dalongrong/xxl-job-executor--saveor......
  • Redis的Java客户端——SpringDataRedis、RedisTemplate、StringRedisTemplate
     版权声明:本文为CSDN博主「我爱布朗熊」的原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/weixin_51351637/article/details/127502799一、初步了解SpringDataRedisSpringData是Spring中数据操作的模块,包括对各种数据库的集......
  • 搭建游戏服务端初始准备
    1.  开发游戏服务端,一般会从编写联网的程序着手,因为游戏服务端最重要的任务是处理网络请求。尽管网络编程很重要,但从“学以致用”的角度来看,先“不择手段”(用现成的库)把游戏做出来,再深入了解,也未尝不可。......
  • Oracle 学习1_Oracle的客户端
    Oracle的客户端:1.命令行2.SQL*Plus3.isqlpluse 4.plsqldev/DBeaver.... ......
  • C++ libwebsockets搭建WebSocket服务端及Http客户端、服务端
    https://blog.csdn.net/fantasysolo/article/details/88908948  概念WebRTCWebRTC,名称源自网页即时通信(英语:WebReal-TimeCommunication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的API。它于2011年6月1日开源并在Google、Mozilla、Opera支持下被纳入万维网联......
  • uniCloud-用db schema在客户端访问数据库
    先下载所有dbschema在前端代码中直接访问数据库表拿数据index.vue<template> <viewclass="content"> <viewv-for="itemindataList":key="item._id"> {{item.name}}---{{item.gender}}---{{item.age}} </view> <......
  • Linux网盘程序——客户端(完整注释版)
    客户端#include<cstdio>//C++标准库的头文件#include<unistd.h>//Unix标准头文件#include<arpa/inet.h>//通常用于处理IP地址和套接字地址的转换#include<string.h>//字符串头文件#include<stdlib.h>//包含了一些标准库函数,用于内存分配、释放以及其他一些通用的实用功能#in......
  • MySQL客户端命令
    目录MySQL客户端命令优化命令提示符mysqlmysqladminmysqldumpSQL层SQL语句DDL(DatabaseDefinitionLanguage)数据定义语言数据库create增:建库drop删:删库alter改表操作create增:建表数据类型数字类型字符串类型枚举类型浮点型时间戳类型字段属性(约束)drop删alter改DMLinsert增delete......
  • 获取emclient客户端许可证并注册
    https://www.emclient.com/free-license.aspx......