WebSocket是一种在单个TCP连接上进行全双工通信的协议。允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

一、参考网址:

libwebsockets官网:  https://libwebsockets.org/

libwebsockets的API:https://libwebsockets.org/lws-api-doc-master/html/modules.html

https://libwebsockets.org/libwebsockets-api-doc.html

cmake 去除openssl库依赖.vs2010编译.

建立双工通道,接下来就可以进行收发数据, 当连接成功之后,通过不断询问service 是否有回调事件,来处理对应的回调事件.

// ConSoleWebS_Test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

// Consolelibwebs.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

#include "include/libwebsockets.h"
#include <signal.h>
#include <string.h>
#include <map>
using namespace std;
map<long,string>map_wsi_token;// 存wsi指针为key, token为字符串

static volatile int exit_sig = 0;
#define MAX_PAYLOAD_SIZE  10 * 1024

void sighdl(int sig) {
    lwsl_notice("%d traped", sig);
    exit_sig = 1;
}

/**
 * 会话上下文对象,结构根据需要自定义
 */
struct session_data {
    int msg_count;
    unsigned char buf[LWS_PRE + MAX_PAYLOAD_SIZE];
    int len;
    bool bin;
    bool fin;
};

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_PROTOCOL_INIT:
        break;
    case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: //这里的wsi中才有url内容
        {        
            char content_length_str[200] = {0};
            lws_hdr_copy(wsi,content_length_str,200,(lws_token_indexes)0);
            //TODO: 获取最新的mythread->GetNewToken(chartoken); 替换 a2abd43dfooepcxw
            //.例如:
            //char chartoken[100] = {0};
            //mythread->GetNewToken(chartoken);
            //if(strstr(content_length_str,chartoken) != NULL)
            //{
            //    map_wsi_token.insert(pair<long,string>(long(wsi),string(chartoken)));
            //}
            //else
            //    return -1;
        }
        break;
    case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
        break;
    case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
        break;
    case LWS_CALLBACK_WSI_CREATE:
        break;
    case LWS_CALLBACK_HTTP:
        break;
    case LWS_CALLBACK_ADD_HEADERS:
        break;
    case LWS_CALLBACK_FILTER_HTTP_CONNECTION:
        break;
    case LWS_CALLBACK_ESTABLISHED:       // 当服务器和客户端完成握手后
        printf("Client connect!\n");
        break;
    case LWS_CALLBACK_SESSION_INFO:
        break;
    case LWS_CALLBACK_RECEIVE:           // 当接收到客户端发来的帧以后
        {
            map<long,string>::iterator iter = map_wsi_token.find(long(wsi));
            if(iter != map_wsi_token.end())
            {
                //TODO: 获取最新的mythread->gettoken(char); 替换 a2abd43dfooepcxw
                string strtoken = iter->second;
                
                if(strtoken.find("a2abd43dfooepcxw") >= -1)
                {
                    return -1;
                }
            }
            else
            {
                return -1;
            }

// 判断是否最后一帧
            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;
            printf("recvied message:%s\n", in);

// 需要给客户端应答时,触发一次写回调
            lws_callback_on_writable(wsi);
        }
        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;
    case LWS_CALLBACK_LOCK_POLL:
    case LWS_CALLBACK_UNLOCK_POLL:
        break;
    case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
        map<long,string>::iterator iter = map_wsi_token.find(long(wsi));
        if(iter != map_wsi_token.end())
        {
            map_wsi_token.erase(iter);
        }
        break;
    }
    // 回调函数最终要返回0,否则无法创建服务器
    return 0;
}

/**
 * 支持的WebSocket子协议数组
 * 子协议即JavaScript客户端WebSocket(url, protocols)第2参数数组的元素
 * 你需要为每种协议提供回调函数
 */
struct lws_protocols protocols[] = {
    {
        //协议名称,协议回调,接收缓冲区大小
        "http", protocol_my_callback, sizeof(struct session_data), MAX_PAYLOAD_SIZE,
    },
    {
        //协议名称,协议回调,接收缓冲区大小
        "ws", protocol_my_callback, sizeof(struct session_data), MAX_PAYLOAD_SIZE,
    },
    {

NULL, NULL,   0 // 最后一个元素固定为此格式
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    // 信号处理函数
    signal(SIGTERM, sighdl);

struct lws_context_creation_info ctx_info = { 0 };
    ctx_info.port = 9002;
    ctx_info.iface = NULL; // 在所有网络接口上监听
    ctx_info.protocols = protocols;
    ctx_info.gid = -1;
    ctx_info.uid = -1;
    ctx_info.options = LWS_SERVER_OPTION_VALIDATE_UTF8;

// ctx_info.ssl_ca_filepath = "../ca/ca-cert.pem";
  //  ctx_info.ssl_cert_filepath = "./server-cert.pem";
   // ctx_info.ssl_private_key_filepath = "./server-key.pem";
  //  ctx_info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
    //ctx_info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;

struct lws_context* context = lws_create_context(&ctx_info);
    while (!exit_sig) {
        lws_service(context, 1000);
    }
    lws_context_destroy(context);

return 0;
}

c++ libwebsocket库应用开发相关推荐

  1. c++ libwebsocket库应用开发2

    1.向web端发送二进制数据与文本数据时注意 //lws_write(wsi, data->buf+LWS_PRE, isz, LWS_WRITE_BINARY);  //lws_write(w ...

  2. 手把手教你写C语言的动态库的开发

    前言 动态库的概念: 动态库提供了一种方法,使进程可以调用不属于其可执行代码的函数.函数的可执行代码位于一个 DLL 文件中, 该 DLL 包含一个或多个已被编译.链接并与使用它们的进程分开存储的函数 ...

  3. 树莓派UART串口编程--使用wiringPi库-C开发【1-基础应用】

    一.串口说明 莓派3B+上UART串口位于GPIO的8脚和10脚,分别为GPIO8=Tx,GPIO10=Rx.在连接外部接口时,需要交换接口,即GPIO8连接到外设的Rx,GPIO10连接到外设的Tx ...

  4. Android 须知2019流行的框架库及开发语言

    Android 须知2019流行的框架库及开发语言 导语 2018 已经悄悄的走了,2019 也已经匆匆的来了,我们在总结过去的同时,也要展望一下未来,来规划一下今年要学哪些新技术.这几年优秀Andr ...

  5. 预告:公共语言运行库(CLR)开发系列课程(4):COM Interop进阶

    这次我主要讲RCW的原理,生命周期,引用计数,套间,System.__ComObject,事件调用原理等内容.CCW由于时间限制就不涉及了,毕竟大家还是以使用RCW为主. 感兴趣的朋友可以在下面注册: ...

  6. STM32F103C8T6基础开发教程(HAL库)—开发环境配置

    STM32F103C8T6基础开发教程目录 STM32F103C8T6基础开发教程(HAL库)-开发环境配置 STM32F103C8T6基础开发教程(HAL库)-Keil添加注释的快捷键 STM32F ...

  7. Maven环境下测试库和开发库的配置策略以及支持工具

    在项目的开发和测试上,团队往往有这样一些情况和要求: 1. 只要是走单元测试,必然要清库 2. 开发人员不想每次重新构建都从一个空库开始重新输入数据,他们希望能够使用一个已有的库 3. 如果新版本的数 ...

  8. 通过python各种开源库,开发一个适合大部分公司测试项目框架,确定名字AutoTestProjects

    通过python各种开源库,开发一个适合大部分公司测试项目框架,确定名字AutoTestProjects 一,简介 1.目前市场上的框架一般都需要码农进行编写,对测试小白非常的不友好,而且现在整个IT ...

  9. 基于WEB的多媒体素材管理库的开发与应用,免费分享

    今天将为大家分析一个基于WEB的多媒体素材管理库的开发与应用(进入21世纪以来,随着计算机信息技术的发展,在世界范围内的教育领域中,多媒体技术已经被作为一种新兴的教学手段而广泛应用,对于计算机得辅助教 ...

最新文章

  1. 差分约束系统——建模与求解
  2. ce5e.cn fadian.php,空包网 PHP mysql
  3. c+ +三角函数_C ++中的三角函数
  4. 《SpringCloud超级入门》使用Eureka编写服务消费者《十一》
  5. 10 个令人惊喜的 jQuery 插件推荐
  6. .NET BackgroundWorker的一般使用方式
  7. 公众号菜单 点击推送图片素材_公众号菜单栏如何设置
  8. EnterpriseDb公司的Postgres Enterprise Manager 安装图解
  9. 应用安全 - Web安全 - 逻辑漏洞整理
  10. ADF文件数据结构解析和ADF文件读写
  11. 嵌入式linux地图,基于嵌入式Linux的MapInfo格式地图显示
  12. 读《C专家编程》笔记-关于内存泄漏
  13. tomcat内存溢出全记录
  14. 淘宝客微信机器人搭建教程分享
  15. Java获取IP归属地
  16. cajviewer阅读器打不开怎么解决
  17. IoT原型开发利用现成的单板设计---凯利讯半导体
  18. Overload和Override
  19. vs 2019 自带 反编译 与 Reflector 反编译工具比较
  20. 帝国CMS采集插件哪个好用?帝国CMS采集文章教程

热门文章

  1. 堃博医疗创上市以来新低:年内跌幅超八成,市值累计蒸发90亿港元
  2. 大数据学习线路及各阶段学习书籍推荐
  3. DT时代,大数据分析都包含了哪些技术?
  4. Waifu2x-Extension-GUI 图片 GIF 视频 人工智能放大与降噪(超分辨率) v1.50.2 更新
  5. Java实现的LU分解,高斯消去法求线性方程组的解
  6. 避免繁琐步骤,在Ubuntu22.04安装cuda、cudnn及pytorch
  7. 智能猪场APP开发有哪些功能特点?
  8. 深入理解--ES之倒排索引
  9. Java 编写Validator验证器
  10. 用随机投点法计算pi值matlab,(原创精品)用随机投点法计算π值【Compute π with dartpoint randomly】.doc...