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



