1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > wss协议 c 服务器 利用LIBWEBSOCKETS写WS WSS服务端和客户端

wss协议 c 服务器 利用LIBWEBSOCKETS写WS WSS服务端和客户端

时间:2019-04-24 03:04:38

相关推荐

wss协议 c 服务器 利用LIBWEBSOCKETS写WS WSS服务端和客户端

libwebsockets是一款轻量级用来开发服务器和客户端的C库。按照官方(/)给出的介绍来看,它不仅支持ws,wss还同时支持http与https,可以轻轻松松结合openssl等库来实现ssl加密。

实现websocket服务本身也是libwebsockets库的初衷,本篇文章将讲解如何利用libwebsockets写ws、wss服务端和客户端。

服务端:

server.c#include"libwebsockets.h"

#include

#include

staticvolatileintexit_sig=0;

#defineMAX_PAYLOAD_SIZE10*1024

voidsighdl(intsig){

lwsl_notice("%dtraped",sig);

exit_sig=1;

}

/**

*会话上下文对象,结构根据需要自定义

*/

structsession_data{

intmsg_count;

unsignedcharbuf[LWS_PRE+MAX_PAYLOAD_SIZE];

intlen;

boolbin;

boolfin;

};

staticintprotocol_my_callback(structlws*wsi,enumlws_callback_reasonsreason,void*user,void*in,size_tlen){

structsession_data*data=(structsession_data*)user;

switch(reason){

caseLWS_CALLBACK_ESTABLISHED://当服务器和客户端完成握手后

printf("Clientconnect!\n");

break;

caseLWS_CALLBACK_RECEIVE://当接收到客户端发来的帧以后

//判断是否最后一帧

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("recviedmessage:%s\n",in);

//需要给客户端应答时,触发一次写回调

lws_callback_on_writable(wsi);

break;

caseLWS_CALLBACK_SERVER_WRITEABLE://当此连接可写时

lws_write(wsi,&data->buf[LWS_PRE],data->len,LWS_WRITE_TEXT);

//下面的调用允许在此连接上接收数据

lws_rx_flow_control(wsi,1);

break;

}

//回调函数最终要返回0,否则无法创建服务器

return0;

}

/**

*支持的WebSocket子协议数组

*子协议即JavaScript客户端WebSocket(url,protocols)第2参数数组的元素

*你需要为每种协议提供回调函数

*/

structlws_protocolsprotocols[]={

{

//协议名称,协议回调,接收缓冲区大小

"ws",protocol_my_callback,sizeof(structsession_data),MAX_PAYLOAD_SIZE,

},

{

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

}

};

intmain(intargc,char**argv)

{

//信号处理函数

signal(SIGTERM,sighdl);

structlws_context_creation_infoctx_info={0};

ctx_info.port=8000;

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;

structlws_context*context=lws_create_context(&ctx_info);

while(!exit_sig){

lws_service(context,1000);

}

lws_context_destroy(context);

return0;

}

编译脚本,compile.sh#########################################################################

#FileName:compile.sh

#Author:loon

#mail:2453419889@

#CreatedTime:09月07日星期五10时08分52秒

#########################################################################

#!/bin/bash

libdir=libwebsockets

g++-g-oserverserver.c-I$libdir/include-L$libdir/lib-lwebsockets

客户端

client.c#include"libwebsockets.h"

#include

staticvolatileintexit_sig=0;

#defineMAX_PAYLOAD_SIZE10*1024

voidsighdl(intsig){

lwsl_notice("%dtraped",sig);

exit_sig=1;

}

/**

*会话上下文对象,结构根据需要自定义

*/

structsession_data{

intmsg_count;

unsignedcharbuf[LWS_PRE+MAX_PAYLOAD_SIZE];

intlen;

};

/**

*某个协议下的连接发生事件时,执行的回调函数

*

*wsi:指向WebSocket实例的指针

*reason:导致回调的事件

*user库为每个WebSocket会话分配的内存空间

*in某些事件使用此参数,作为传入数据的指针

*len某些事件使用此参数,说明传入数据的长度

*/

intcallback(structlws*wsi,enumlws_callback_reasonsreason,void*user,void*in,size_tlen){

structsession_data*data=(structsession_data*)user;

switch(reason){

caseLWS_CALLBACK_CLIENT_ESTABLISHED://连接到服务器后的回调

lwsl_notice("Connectedtoserverok!\n");

break;

caseLWS_CALLBACK_CLIENT_RECEIVE://接收到服务器数据后的回调,数据为in,其长度为len

lwsl_notice("Rx:%s\n",(char*)in);

break;

caseLWS_CALLBACK_CLIENT_WRITEABLE://当此客户端可以发送数据时的回调

if(data->msg_count

//前面LWS_PRE个字节必须留给LWS

memset(data->buf,0,sizeof(data->buf));

char*msg=(char*)&data->buf[LWS_PRE];

data->len=sprintf(msg,"你好%d",++data->msg_count);

lwsl_notice("Tx:%s\n",msg);

//通过WebSocket发送文本消息

lws_write(wsi,&data->buf[LWS_PRE],data->len,LWS_WRITE_TEXT);

}

break;

}

return0;

}

/**

*支持的WebSocket子协议数组

*子协议即JavaScript客户端WebSocket(url,protocols)第2参数数组的元素

*你需要为每种协议提供回调函数

*/

structlws_protocolsprotocols[]={

{

//协议名称,协议回调,接收缓冲区大小

"ws",callback,sizeof(structsession_data),MAX_PAYLOAD_SIZE,

},

{

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

}

};

intmain(){

//信号处理函数

signal(SIGTERM,sighdl);

//用于创建vhost或者context的参数

structlws_context_creation_infoctx_info={0};

ctx_info.port=CONTEXT_PORT_NO_LISTEN;

ctx_info.iface=NULL;

ctx_info.protocols=protocols;

ctx_info.gid=-1;

ctx_info.uid=-1;

//ssl支持(指定CA证书、客户端证书及私钥路径,打开ssl支持)

ctx_info.ssl_ca_filepath="../ca/ca-cert.pem";

ctx_info.ssl_cert_filepath="./client-cert.pem";

ctx_info.ssl_private_key_filepath="./client-key.pem";

ctx_info.options|=LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;

//创建一个WebSocket处理器

structlws_context*context=lws_create_context(&ctx_info);

charaddress[]="127.0.0.1";

intport=8000;

charaddr_port[256]={0};

sprintf(addr_port,"%s:%u",address,port&65535);

//客户端连接参数

structlws_client_connect_infoconn_info={0};

conn_info.context=context;

conn_info.address=address;

conn_info.port=port;

conn_info.ssl_connection=1;

conn_info.path="./";

conn_info.host=addr_port;

conn_info.origin=addr_port;

conn_info.protocol=protocols[0].name;

//下面的调用触发LWS_CALLBACK_PROTOCOL_INIT事件

//创建一个客户端连接

structlws*wsi=lws_client_connect_via_info(&conn_info);

while(!exit_sig){

//执行一次事件循环(Poll),最长等待1000毫秒

lws_service(context,1000);

/**

*下面的调用的意义是:当连接可以接受新数据时,触发一次WRITEABLE事件回调

*当连接正在后台发送数据时,它不能接受新的数据写入请求,所有WRITEABLE事件回调不会执行

*/

lws_callback_on_writable(wsi);

}

//销毁上下文对象

lws_context_destroy(context);

return0;

}

编译脚本:#########################################################################

#FileName:compile.sh

#Author:loon

#mail:2453419889@

#CreatedTime:09月07日星期五10时22分58秒

#########################################################################

#!/bin/bash

libdir=libwebsockets

g++-g-oclientclient.c-I$libdir/include-L$libdir/build/lib-lwebsockets

————————————————版权声明:本文为CSDN博主「xiaoyaoyou.xyz」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。原文链接:/weixin_39510813/article/details/86728804

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。