栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++ libwebsocket库应用开发

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++ libwebsocket库应用开发

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


#include "include/libwebsockets.h"
#include
#include
#include
using namespace std;
mapmap_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(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::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:%sn", 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::iterator iter = map_wsi_token.find(long(wsi));
        if(iter != map_wsi_token.end())
        {
            map_wsi_token.erase(iter);
        }
        break;
    }
    // 回调函数最终要返回0,否则无法创建服务器
    return 0;
}


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;
}
 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/443812.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号