apt-get source libwebsockets-dev
sudo apt-get install libwebsockets-dev
cd libwebsockets
mkdir build
cd build
cmake ../ -D
参考 README.build.md cmake .. -DCMAKE_BUILD_TYPE=DEBUG
/*
============================================================================
Name : test-websocket.c
Author : cj
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include
#include
#include
#include "clog.h"
#include
struct session_data {
char name[100];
};
static int ws_service_callback(struct lws *wsi,
enum lws_callback_reasons reason, void *user, void *in, size_t size) {
int n;
struct session_data *session = (struct session_data*) user;
switch (reason) {
case LWS_CALLBACK_GET_THREAD_ID:
break;
case LWS_CALLBACK_CLIENT_ESTABLISHED: {
log_d("CLIENT_ESTABLISHED");
char *str = "hello start..";
int len = strlen(str);
unsigned char *out = (unsigned char *) malloc(
sizeof(unsigned char)
* (LWS_SEND_BUFFER_PRE_PADDING + len
+ LWS_SEND_BUFFER_POST_PADDING));
memcpy(out + LWS_SEND_BUFFER_PRE_PADDING, str, len);
n = lws_write(wsi, out + LWS_SEND_BUFFER_PRE_PADDING, len,
LWS_WRITE_TEXT);
//sprintf(session->name, "start....");
//log_d("n=%d", n);
}
break;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
log_d("CONNECTION_ERROR");
return -1;
break;
case LWS_CALLBACK_CLOSED:
log_d("LWS_CALLBACK_CLOSED");
break;
case LWS_CALLBACK_WSI_DESTROY:
log_d("LWS_CALLBACK_WSI_DESTROY");
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
log_d("session:%s, recv(len=%d)>%s", session->name, size, (char * ) in);
{
char *str = "hello world. recv";
int len = strlen(str);
unsigned char *out = (unsigned char *) malloc(
sizeof(unsigned char) * (LWS_PRE + len));
memcpy(out + LWS_PRE, str, len);
n = lws_write(wsi, out + LWS_PRE, len, LWS_WRITE_BINARY);
//log_d("n=%d", n);
n = lws_callback_on_writable(wsi);
//log_d("n=%d", n);
}
break;
case LWS_CALLBACK_CLIENT_WRITEABLE: {
//log_d("LWS_CALLBACK_CLIENT_WRITEABLE");
char *str = "write.....";
int len = strlen(str);
unsigned char *out = (unsigned char *) malloc(
sizeof(unsigned char) * (LWS_PRE + len));
memcpy(out + LWS_PRE, str, len);
n = lws_write(wsi, out + LWS_PRE, len, LWS_WRITE_BINARY);
n = lws_callback_on_writable(wsi);
}
break;
default:
break;
}
return 0;
}
#ifdef WCLIENT
int main(int argc,char **argv) {
#else
int main_client() {
#endif
const char *address = "127.0.0.1";
struct lws_context *context = NULL;
struct lws_context_creation_info info;
struct lws *wsi = NULL;
struct lws_protocols protocol;
// struct sigaction act;
// act.sa_handler = INT_HANDLER;
// act.sa_flags = 0;
// sigemptyset(&act.sa_mask);
// sigaction( SIGINT, &act, 0);
memset(&info, 0, sizeof info);
info.port = CONTEXT_PORT_NO_LISTEN;
info.iface = NULL;
info.protocols = &protocol;
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.extensions = NULL;
info.gid = -1;
info.uid = -1;
info.options = 0;
protocol.name = "abc";
protocol.callback = &ws_service_callback;
protocol.per_session_data_size = sizeof(struct session_data);
protocol.rx_buffer_size = 65535;
protocol.id = 0;
protocol.user = NULL;
context = lws_create_context(&info);
log_d("[Main] context created.");
if (context == NULL) {
log_d("[Main] context is NULL.");
return -1;
}
#if 0
wsi = lws_client_connect(context, address, 1883, 0, "/123",
"111:5000",
NULL, protocol.name, -1);
#else
struct lws_client_connect_info i;
memset(&i, 0, sizeof(i));
i.port = 8080;
i.address = address;
i.path = "abc";
i.context = context;
i.ssl_connection = 0;
i.host = i.address;
i.origin = i.address;
i.ietf_version_or_minus_one = -1;
i.client_exts = NULL;
i.protocol = "abc";
wsi = lws_client_connect_via_info(&i);
#endif
if (wsi == NULL) {
log_d("[Main] wsi create error.");
return -1;
}
log_d("start....");
int n = 0;
while (n >= 0) {
//当连接断开时需要重新连接在这使用标志位
//if conflag==0 lws_client_connect_via_info
n = lws_service(context, 50);
}
lws_context_destroy(context);
log_d("close....");
return EXIT_SUCCESS;
}
LWS_CALLBACK_CLIENT_ESTABLISHED | 第一次连接 这是客户端 |
LWS_CALLBACK_CLIENT_RECEIVE | 接收到数据 这是客户端 |
LWS_CALLBACK_CLIENT_WRITEABLE | 可以发送数据了 |
LWS_CALLBACK_WSI_DESTROY | 正在销毁,在这可以释放ESTABLISHED时malloc的数据 |
/*
============================================================================
Name : test-websocket.c
Author : cj
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include
#include
#include
#include "clog.h"
#include
struct session_data {
char name[100];
};
static int ws_service_callback(struct lws *wsi,
enum lws_callback_reasons reason, void *user, void *in, size_t size) {
int n;
struct session_data *session = (struct session_data*) user;
switch (reason) {
case LWS_CALLBACK_GET_THREAD_ID:
break;
case LWS_CALLBACK_ESTABLISHED: {
log_d("ESTABLISHED");
char *str = "hello start..";
int len = strlen(str);
unsigned char *out = (unsigned char *) malloc(
sizeof(unsigned char)
* (LWS_SEND_BUFFER_PRE_PADDING + len
+ LWS_SEND_BUFFER_POST_PADDING));
memcpy(out + LWS_SEND_BUFFER_PRE_PADDING, str, len);
n = lws_write(wsi, out + LWS_SEND_BUFFER_PRE_PADDING, len,
LWS_WRITE_TEXT);
sprintf(session->name, "start....");
}
break;
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
log_d("CONNECTION_ERROR");
return -1;
break;
case LWS_CALLBACK_CLOSED:
log_d("LWS_CALLBACK_CLOSED");
break;
case LWS_CALLBACK_WSI_DESTROY:
log_d("LWS_CALLBACK_WSI_DESTROY");
break;
case LWS_CALLBACK_RECEIVE:
//log_d("session:%s, recv(len=%d)>%s", session->name, size, (char * ) in);
{
char *str = "hello world. recv";
int len = strlen(str);
unsigned char *out = (unsigned char *) malloc(
sizeof(unsigned char) * (LWS_PRE + len));
memcpy(out + LWS_PRE, str, len);
n = lws_write(wsi, out + LWS_PRE, len, LWS_WRITE_BINARY);
n = lws_callback_on_writable(wsi);
}
break;
case LWS_CALLBACK_SERVER_WRITEABLE: {
//log_d("LWS_CALLBACK_CLIENT_WRITEABLE");
char *str = "write....ser.";
int len = strlen(str);
unsigned char *out = (unsigned char *) malloc(
sizeof(unsigned char) * (LWS_PRE + len));
memcpy(out + LWS_PRE, str, len);
n = lws_write(wsi, out + LWS_PRE, len, LWS_WRITE_BINARY);
n = lws_callback_on_writable(wsi);
}
break;
default:
break;
}
return 0;
}
int main(void) {
struct lws_context *context = NULL;
struct lws_context_creation_info info;
struct lws_protocols protocol;
// struct sigaction act;
// act.sa_handler = INT_HANDLER;
// act.sa_flags = 0;
// sigemptyset(&act.sa_mask);
// sigaction( SIGINT, &act, 0);
memset(&info, 0, sizeof info);
info.port = 8080;
info.iface = NULL;
info.protocols = &protocol;
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.extensions = NULL;
info.gid = -1;
info.uid = -1;
info.options = 0;
protocol.name = "abc";
protocol.callback = &ws_service_callback;
protocol.per_session_data_size = sizeof(struct session_data);
protocol.rx_buffer_size = 65535;
protocol.id = 0;
protocol.user = NULL;
context = lws_create_context(&info);
log_d("[Main] context created.");
if (context == NULL) {
log_d("[Main] context is NULL.");
return -1;
}
log_d("start....");
int n = 0;
while (n >= 0) {
n = lws_service(context, 50);
}
lws_context_destroy(context);
return EXIT_SUCCESS;
}
LWS_CALLBACK_ESTABLISHED | 收到客户端连接,在这里可以注册user (session_data) 到一个线程安全Lock的链表上 user中可以添加一个发送数据队列 |
LWS_CALLBACK_RECEIVE | 收到客户端数据,后续需要写数据可以添加使用 lws_callback_on_writable 来处理写事件 |
LWS_CALLBACK_SERVER_WRITEABLE | 可以写数据到客户端,添加 lws_callback_on_writable, 这时可以把session中存储的代发送数据发送出去 |
LWS_CALLBACK_WSI_DESTROY | 释放数据开始 ,这里请取消注册到线程安全客户端队列里面 |
LWS_CALLBACK_CLOSED | 有时候不会到这来,最好在DESTROY中处理 |
对于libwebsockets高级应用方面,我参考了 https://blog.csdn.net/sonysuqin/article/details/82050970
里面说的 libwebsockets IO的优化
在这里可以参考一下mqtt服务器mosquitto