webcomm与前端的通讯-websocket服务器操作流程

#include <libwebsockets.h>
#include <pthread.h>
#include <string.h>#define MAX_PAYLOAD_SIZE   (4096)/** 开启确认才有重发的机制 */
typedef struct comm_packet {void        *content;               /* is malloc'd */size_t        content_len;uint8_t     enable_ack;             /* 是否需要响应 0:不需要响应 1:需要响应 */uint8_t        retry_cnt;              /* 重发的次数(ms)    */
} comm_packet_t;/* one of these created for each message */
typedef struct msg {comm_packet_t   *payload; /* is malloc'd */size_t          len;
} msg_t;/* one of these is created for each client connecting to us */
struct per_session_data__cetwebsocket {struct per_session_data__cetwebsocket *pss_list;struct lws *wsi;uint32_t tail;struct lws_ring *ring;         /* ringbuffer holding unsent messages */
};/* one of these is created for each vhost our protocol is used with */
struct per_vhost_data__cetwebsocket {struct lws_context *context;struct lws_vhost *vhost;const struct lws_protocols *protocol;struct per_session_data__cetwebsocket *pss_list; /* linked-list of live pss*/
};static int
callback_protocol_cetwebsocket_server(struct lws *wsi, enum lws_callback_reasons reason,void *user, void *in, size_t len);#define LWS_PLUGIN_PROTOCOL_CETWEBSOCKET \{ \"cet-webserver", /* "cet-webserver" */ \callback_protocol_cetwebsocket_server, \sizeof(struct per_session_data__cetwebsocket), \2048, \0, NULL, 0 \}static struct lws_protocols sg_protocols[] = {{ "http", lws_callback_http_dummy, 0, 0 }, LWS_PLUGIN_PROTOCOL_CETWEBSOCKET,{ NULL, NULL, 0, 0 } /* terminator */
};static int sg_interrupted = 0;/* destroys the message when everyone has had a copy of it */
static void
cetwebsocket_destroy_message(void *_msg)
{msg_t *message = _msg;comm_packet_t *ppacket = (comm_packet_t *)message->payload;free(ppacket->content);ppacket->content = NULL;free(message->payload);message->payload = NULL;message->len = 0;
}static struct per_session_data__cetwebsocket **
cetwebsocket_traverse_find(struct per_vhost_data__cetwebsocket *vhd, struct per_session_data__cetwebsocket *pss)
{   ASSERT_PARAM_CHECK(vhd, NULL);ASSERT_PARAM_CHECK(pss, NULL);struct per_session_data__cetwebsocket **ppss = NULL;for (ppss = &(vhd->pss_list); *ppss; ppss = &((*ppss)->pss_list)) {if ((*ppss) == pss) {return ppss;}}return NULL;
}static struct per_session_data__cetwebsocket *
cetwebsocket_client_remove(struct per_vhost_data__cetwebsocket *vhd, struct per_session_data__cetwebsocket *pss)
{   ASSERT_PARAM_CHECK(vhd, NULL);ASSERT_PARAM_CHECK(pss, NULL);struct per_session_data__cetwebsocket **ppss = NULL;if (NULL != (ppss = cetwebsocket_traverse_find(vhd, pss))) {lws_ring_destroy(pss->ring);*ppss = pss->pss_list;        return *ppss;}return pss;
}static int
cetwebsocket_insert_ring(struct per_session_data__cetwebsocket *pss, const char *func_id, const char *mid, uint8_t enable_ack, const void *content, int contentlen)
{   int n = 0;msg_t amsg;ASSERT_PARAM_CHECK(pss, -1);ASSERT_PARAM_CHECK(content, -1);n = (int)lws_ring_get_count_free_elements(pss->ring); if (!n) {return -1;}memset(&amsg, 0x00, sizeof(amsg));/* notice we over-allocate by LWS_PRE */amsg.payload = calloc(sizeof(char), sizeof(comm_packet_t));if (!amsg.payload) {return -1;}/* notice we over-allocate by LWS_PRE */amsg.payload->content = calloc(sizeof(char), LWS_PRE + contentlen + 1);if (!amsg.payload->content) {return -1;}amsg.payload->enable_ack    = enable_ack;amsg.payload->retry_cnt        = 0;amsg.payload->content_len   = contentlen;amsg.len = amsg.payload->content_len + sizeof(comm_packet_t);memcpy((char *)amsg.payload->content + LWS_PRE, content, contentlen);/** 将实时消息插入到环形缓存中 */if (!lws_ring_insert(pss->ring, &amsg, 1)) {cetwebsocket_destroy_message(&amsg);return -1;}return 0;
}static comm_packet_t *
cetwebsocket_get_packet(struct lws_ring *ring, uint32_t *tail)
{msg_t  *pmsg = NULL;ASSERT_PARAM_CHECK(ring, NULL);pmsg = (msg_t *)lws_ring_get_element(ring, tail);return (NULL == pmsg)? NULL : (comm_packet_t *)pmsg->payload;
}static int
cetwebsocket_response_handler(struct per_session_data__cetwebsocket *pss, const char *mid)
{   comm_packet_t *ppacket;ASSERT_PARAM_CHECK(pss, -1);ASSERT_PARAM_CHECK(mid, -1);ppacket = cetwebsocket_get_packet(pss->ring, &pss->tail);         if (NULL == ppacket)return -1;if (ppacket->enable_ack) {   // ack respenseif (0 == strcmp(mid, ppacket->mid)) {lws_ring_consume_single_tail(pss->ring, &pss->tail, 1);          }} else {; // not ack respense}return 0;
}static int
cetwebsocket_server_create(struct lws *wsi)
{       struct per_vhost_data__cetwebsocket *vhd = NULL;vhd = (struct per_vhost_data__cetwebsocket *)lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),lws_get_protocol(wsi), sizeof(struct per_vhost_data__cetwebsocket));vhd->context = lws_get_context(wsi);vhd->protocol = lws_get_protocol(wsi);vhd->vhost = lws_get_vhost(wsi);vhd->pss_debug_count = 0;   vhd->pss_other_count = 0;vhd->pss_list = NULL;sg_ptr_websockets->vhost = vhd;return 0;
}static int
cetwebsocket_session_create(struct lws *wsi, struct per_vhost_data__cetwebsocket *vhd, struct per_session_data__cetwebsocket *pss)
{   char    *cookie_id = NULL;char     buffer[FIELDS_SIZE] = {0};ASSERT_PARAM_CHECK(wsi, -1);ASSERT_PARAM_CHECK(vhd, -1);ASSERT_PARAM_CHECK(pss, -1);pss->tail = 0;pss->wsi = wsi;pss->ring = lws_ring_create(sizeof(msg_t), (FIELDS_SIZE), cetwebsocket_destroy_message);        if (!pss->ring) {            return -1;}lws_ll_fwd_insert(pss, pss_list, vhd->pss_list);return 0;
}static int
cetwebsocket_server_write(struct lws *wsi, struct per_vhost_data__cetwebsocket *vhd, struct per_session_data__cetwebsocket *pss)
{       int     len;comm_packet_t *ppacket;ASSERT_PARAM_CHECK(wsi, -1);ASSERT_PARAM_CHECK(vhd, -1);ASSERT_PARAM_CHECK(pss, -1);if (NULL == cetwebsocket_traverse_find(vhd, pss)) {return -1;}if (NULL == (ppacket = cetwebsocket_get_packet(pss->ring, &pss->tail))) {return -1;}len = lws_write(wsi, ((unsigned char *)ppacket->content) + LWS_PRE, ppacket->content_len, LWS_WRITE_TEXT);if (len < (int)ppacket->content_len) {return -1;}if (!ppacket->enable_ack || ppacket->retry_cnt > RETRY_MAX_CNT) {     lws_ring_consume_single_tail(pss->ring, &pss->tail, 1);}return 0;
}static int
callback_protocol_cetwebsocket_server(struct lws *wsi, enum lws_callback_reasons reason,void *user, void *in, size_t len)
{struct per_session_data__cetwebsocket *pss = (struct per_session_data__cetwebsocket *)user;struct per_vhost_data__cetwebsocket *vhd = sg_ptr_websockets->vhost;switch (reason) {case LWS_CALLBACK_PROTOCOL_INIT:      cetwebsocket_server_create(wsi);break;case LWS_CALLBACK_PROTOCOL_DESTROY:break;case LWS_CALLBACK_ESTABLISHED:{  cetwebsocket_session_create(wsi, vhd, pss);break;}case LWS_CALLBACK_CLOSED:     cetwebsocket_client_remove(vhd, pss);break;case LWS_CALLBACK_SERVER_WRITEABLE:{ cetwebsocket_server_write(wsi, vhd, pss);break;}case LWS_CALLBACK_RECEIVE:{ if (vhd->pss_list) {     cetwebsocket_server_receive(wsi, vhd, pss, in, len);}       break;}default:break;}return 0;
}static int
cetwebsocket_retry_writable_handler(struct per_vhost_data__cetwebsocket *vhost)
{boolean        is_writable = true;comm_packet_t   *ppacket = NULL;   struct per_session_data__cetwebsocket *pss = NULL;ASSERT_PARAM_CHECK(vhost, -1);for (pss = vhost->pss_list; pss; pss = pss->pss_list) {ppacket = cetwebsocket_get_packet(pss->ring, &pss->tail);            if (NULL == ppacket)continue;if (ppacket->enable_ack) {if (ppacket->retry_cnt <= RETRY_MAX_CNT) {ppacket->retry_cnt += 1;} else {is_writable = false;}}if (true == is_writable) {lws_callback_on_writable(pss->wsi);}}return 0;
}int main(int argc, char * const argv[])
{struct lws_context_creation_info info;struct lws_context *context; int n = 0/* , logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE| LLL_INFO | LLL_PARSER | LLL_HEADER | LLL_EXT | LLL_CLIENT | LLL_LATENCY | LLL_DEBUG *//* for LLL_ verbosity above NOTICE to be built into lws,* lws must have been configured and built with* -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE *//* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER *//* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY *//* | LLL_DEBUG */;lws_set_log_level(0, NULL);memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */info.port = 7681;info.protocols = sg_protocols;info.vhost_name = "localhost";info.ws_ping_pong_interval = 10;info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;info.ssl_cert_filepath = ME_GOAHEAD_SSL_CERTIFICATE;info.ssl_private_key_filepath = ME_GOAHEAD_SSL_KEY;context = lws_create_context(&info);if (!context) {return NULL;}while (n >= 0 && !sg_interrupted) {    n = lws_service(context, 0);lws_cancel_service(context);       }lws_context_destroy(context);return NULL;
}

使用libwebsocket搭建websocket服务器实例相关推荐

  1. websocket 学习--简单使用,nodejs搭建websocket服务器,到模拟股票,到实现聊天室

    websocket简介: WebSocket协议是 HTML5 开始提供的一种基于TCP的一种新的全双工通讯的网络通讯协议.它允许服务器主动发送信息给客户端. 和http协议的不同?? HTTP 协议 ...

  2. 在IIS上搭建WebSocket服务器(三)

    在IIS上搭建WebSocket服务器(三) 原文:在IIS上搭建WebSocket服务器(三) 编写客户端代码 1.新建一个*.html文件. ws = new WebSocket('ws://19 ...

  3. netty系列之:使用netty搭建websocket服务器

    文章目录 简介 netty中的websocket websocket的版本 FrameDecoder和FrameEncoder WebSocketServerHandshaker WebSocketF ...

  4. 项目实战-物联网平台搭建-搭建websocket服务器(三)

    项目目前是有手机app 做客户端,通过app订阅主题并发送消息,mqtt服务器会将数据转存如mysql数据库中,然后再由ws服务端发送到前端展示 下边是大二写的一个mqtt通信app 客户端给温度主题 ...

  5. 【Netty系列】使用Netty搭建WebSocket服务器

    使用Netty搭建WebSocket服务器 引入netty的依赖 <dependency><groupId>io.netty</groupId><artifa ...

  6. 在IIS上搭建WebSocket服务器(一)

    一.搭建环境 1.System.Web.WebSockets需搭建在Windows8及Server2012以上系统的上. 2.在Windows8及Server2012以上系统的上安装IIS和WebSo ...

  7. 20190503(cmake安装,利用libwebsockets库去实现http服务器,websocket服务器,虚拟机安装)

    目录 1.libwebsockets简介安装 2.libwebsockets实现简易http服务器 3.实现简易websocket服务器 4.websocket介绍 5.虚拟机安装 1.libwebs ...

  8. node.js搭建简单服务器,用于前端测试websocket链接方法和性能测试

    WebSocket简介 谈到Web实时推送,就不得不说WebSocket.在WebSocket出现之前,很多网站为了实现实时推送技术,通常采用的方案是轮询 (Polling)和Comet技术,Come ...

  9. 树莓派python实例_树莓派3 搭建 django 服务器的实例

    树莓派3的基本配置 这里接着上一章的搭建过程,在我新购置的树莓派3上完成一个网页服务器的搭建以及后台数据库的相关配置.关于树莓派的玩点实在是太多,限于篇幅不做展开.由于我们仅仅只是搭建一个服务器,所以 ...

最新文章

  1. 读书笔记:《HTML5开发手册》--figure、time、details、mark
  2. 人眼是具有插帧能力的
  3. Linux的账号口令机制及其爆破
  4. Python 切片的简单讲解
  5. SQL数据库高级查询命令(2)
  6. 一步一步使用 DialogFragment 封装链式调用 Dialog
  7. django上课笔记6-MVC,MTV架构-中间件-初识Form组件
  8. Delphi TForm 转 TFrame
  9. Android中CheckBox与CompoundButton源码解析
  10. 计算机网络——透明网桥算法
  11. 关于“软件设计师”考试的感悟分享
  12. Java彩信接口开发经验及具体开发实现
  13. n 以内与 n 互素的元素集合必然形成一个循环群
  14. mysql存密码_存储用户ID和密码到mysql数据库的方法
  15. 高德信息服务器,高德一站式全域出行服务平台:做聪明的出行服务
  16. Linux —— 进程间通信
  17. 半乳糖-人血清白蛋白 Gal-HSA,Gal-PEG-HSA 半乳糖修饰人血清白蛋白
  18. 解决UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xca in position 0: invalid continuation byte
  19. spry菜单栏(一)
  20. python describe include_数据分析pandas之DataFrame.describe() 用法概述

热门文章

  1. 图解外包验收流程V2.0及详细说明实例
  2. icon=newImageIcon()如何加载同一文件夹中的已有图片:
  3. HTML5 网页特殊字符大全(参考)
  4. 《深度思维》跨越式*
  5. 无法找到来自源 nvlddmkm 的事件 ID 14 的描述
  6. 青春有我|众享比特董事长严挺出席上海区块链技术协会5.4上海云相聚活动
  7. 【使用指南】风起亚洲(Fengqi.Asia)上手指南
  8. 编译器扩展-MenuItem
  9. pagehelper oracle用法,Mybatis-PageHelper使用方法
  10. 爬虫之 json 数据处理