封装利用libwebsockets写出的客户端、服务端程序为客户端服务端类
文章目录
- 封装利用libwebsockets写出的客户端、服务端程序为客户端服务端类
- 1.封装
- 2.封装后写wss客户端、服务端
- 3.测试结果
- 4.客户端、服务端类程序
1.封装
我们后续将使用c++来开发程序,因此有必要将用c写成的wss客户端、服务端程序作进一步封装,使其成为wss客户端类和服务端类,这样更便于调用。封装后的程序结构:
ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class$ tree
.
├── client
│ ├── client
│ ├── compile.sh
│ ├── lws_client.cpp
│ ├── lws_client.h
│ └── test.cpp
└── server
├── compile.sh
├── lws_server.cpp
├── lws_server.h
├── server
└── test.cpp
2 directories, 10 files
2.封装后写wss客户端、服务端
封装后写wss客户端和服务端将非常方便,只需要几行即可创建一个客户端或者服务端:
服务端创建测试程序:
#include "lws_server.h"
#include <signal.h>
static int interrupted;
void sigint_handler(int sig)
{
interrupted = 1;
}
int main(int argc,char **argv)
{
signal(SIGINT, sigint_handler);
int n = 0;
lws_server server(8000);
server.init();
lwsl_notice("port:%d\n",server.get_port());
server.set_ssl(NULL,NULL,NULL,0);
server.create();
while(n >= 0 && !interrupted)
n = server.run(1000);
server.destroy();
return 0;
}
客户端创建测试程序:
#include "lws_client.h"
#include <signal.h>
static int interrupted;
void sigint_handler(int sig)
{
interrupted = 1;
}
int main(int argc,char **argv)
{
signal(SIGINT, sigint_handler);
int n = 0;
lws_client client("127.0.0.1",8000);
client.init();
client.set_ssl(NULL,NULL,NULL,0);
client.create();
client.connect(0);
while(n >= 0 && !interrupted)
n = client.run(1000);
client.destroy();
return 0;
}
3.测试结果
运行服务端:
ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class/server$ ./server
[2018/09/12 18:34:56:3472] NOTICE: port:8000
[2018/09/12 18:34:56:3493] NOTICE: Creating Vhost 'default' port 8000, 1 protocols, IPv6 off
运行客户端:
ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class/client$ ./client
[2018/09/12 18:35:43:4919] NOTICE: Creating Vhost 'default' (serving disabled), 1 protocols, IPv6 off
[2018/09/12 18:35:43:4947] NOTICE: Connected to server ok!
[2018/09/12 18:35:43:4964] NOTICE: Tx: 你好 1
[2018/09/12 18:35:43:4987] NOTICE: Tx: 你好 2
[2018/09/12 18:35:43:4994] NOTICE: Rx: 你好 1
[2018/09/12 18:35:43:4999] NOTICE: Rx: 你好 2
[2018/09/12 18:35:43:5000] NOTICE: Tx: 你好 3
[2018/09/12 18:35:43:5007] NOTICE: Rx: 你好 3
服务端:
ubuntu@ubuntu-virtual-machine:~/work/test_libwebsockets/lws_class/server$ ./server
[2018/09/12 18:34:56:3472] NOTICE: port:8000
[2018/09/12 18:34:56:3493] NOTICE: Creating Vhost 'default' port 8000, 1 protocols, IPv6 off
[2018/09/12 18:35:43:4939] NOTICE: Client connect!
[2018/09/12 18:35:43:4979] NOTICE: recvied message:你好 1
[2018/09/12 18:35:43:4989] NOTICE: recvied message:你好 2
[2018/09/12 18:35:43:5001] NOTICE: recvied message:你好 3
测试通信成功。目前服务器为回显服务器,其底层采用的poll机制。
4.客户端、服务端类程序
服务端程序类:
#include "lws_server.h"
#define MAX_PAYLOAD_SIZE (10 * 1024)
static struct lws_context_creation_info ctx_info = { 0 };
static struct lws_context *context = NULL;
struct session_data {
int msg_count;
unsigned char buf[LWS_PRE + MAX_PAYLOAD_SIZE];
int len;
bool bin;
bool fin;
};
lws_server::lws_server(int listen_port)
{
port = listen_port;
}
lws_server::~lws_server()
{
lwsl_notice("析构完成\n");
}
lws_server::lws_server(const lws_server &obj)
{
}
int lws_server::get_port()
{
return port;
}
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_ESTABLISHED:
lwsl_notice("Client connect!\n");
break;
case LWS_CALLBACK_RECEIVE:
data->fin = lws_is_final_fragment( wsi );
data->bin = lws_frame_is_binary( wsi );
lws_rx_flow_control( wsi, 0 );
memcpy( &data->buf[ LWS_PRE ], in, len );
data->len = len;
lwsl_notice("recvied message:%s\n",&data->buf[ LWS_PRE ]);
lws_callback_on_writable( wsi );
data = NULL;
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;
}
return 0;
}
struct lws_protocols protocols[] = {
{
"ws", protocol_my_callback, sizeof( struct session_data ), MAX_PAYLOAD_SIZE,
},
{
NULL, NULL, 0
}
};
void lws_server::init()
{
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;
}
int lws_server::set_ssl(const char* ca_filepath,
const char* server_cert_filepath,
const char*server_private_key_filepath,
bool is_support_ssl)
{
if(!is_support_ssl)
{
ctx_info.ssl_ca_filepath = NULL;
ctx_info.ssl_cert_filepath = NULL;
ctx_info.ssl_private_key_filepath = NULL;
}
else
{
ctx_info.ssl_ca_filepath = ca_filepath;
ctx_info.ssl_cert_filepath = server_cert_filepath;
ctx_info.ssl_private_key_filepath = server_private_key_filepath;
ctx_info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
}
return is_support_ssl;
}
int lws_server::create()
{
context = lws_create_context(&ctx_info);
if (!context) {
lwsl_err("lws_server create failed\n");
return -1;
}
return 1;
}
int lws_server::run(int wait_time)
{
return lws_service(context, wait_time);
}
void lws_server::destroy()
{
lws_context_destroy(context);
}
#ifndef __LWS_SERVER_H__
#define __LWS_SERVER_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif
#include <libwebsockets.h>
class lws_server
{
private:
int port;
public:
lws_server(int listen_port);
~lws_server();
lws_server(const lws_server &obj);
int get_port();
void init();
int set_ssl(const char* ca_filepath,
const char* server_cert_filepath,
const char*server_private_key_filepath,
bool is_support_ssl);
int create();
int run(int wait_time);
void destroy();
};
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
客户端程序类:
#include "lws_client.h"
#define MAX_PAYLOAD_SIZE 10 * 1024
static struct lws_context_creation_info ctx_info = { 0 };
static struct lws_context *context = NULL;
static struct lws_client_connect_info conn_info = { 0 };
static struct lws *wsi = NULL;
struct session_data {
int msg_count;
unsigned char buf[LWS_PRE + MAX_PAYLOAD_SIZE];
int len;
};
int lws_client_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_CLIENT_ESTABLISHED:
lwsl_notice( "Connected to server ok!\n" );
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
lwsl_notice( "Rx: %s\n", (char *) in );
break;
case LWS_CALLBACK_CLIENT_WRITEABLE:
if ( data->msg_count < 3 ) {
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 );
lws_write( wsi, &data->buf[ LWS_PRE ], data->len, LWS_WRITE_TEXT );
}
break;
default:
break;
}
return 0;
}
struct lws_protocols protocols[] = {
{
"ws", lws_client_callback, sizeof( struct session_data ), MAX_PAYLOAD_SIZE,
},
{
NULL, NULL, 0
}
};
lws_client::lws_client(char *_address,int _port)
{
server_address = _address;
port = _port;
}
lws_client::~lws_client()
{
lwsl_notice("析构完成\n");
}
lws_client::lws_client(const lws_client &obj)
{
}
void lws_client::init()
{
ctx_info.port = CONTEXT_PORT_NO_LISTEN;
ctx_info.iface = NULL;
ctx_info.protocols = protocols;
ctx_info.gid = -1;
ctx_info.uid = -1;
}
int lws_client::set_ssl(const char* ca_filepath,
const char* server_cert_filepath,
const char*server_private_key_filepath,
bool is_support_ssl)
{
if(!is_support_ssl)
{
ctx_info.ssl_ca_filepath = NULL;
ctx_info.ssl_cert_filepath = NULL;
ctx_info.ssl_private_key_filepath = NULL;
}
else
{
ctx_info.ssl_ca_filepath = ca_filepath;
ctx_info.ssl_cert_filepath = server_cert_filepath;
ctx_info.ssl_private_key_filepath = server_private_key_filepath;
ctx_info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
}
return is_support_ssl;
}
int lws_client::create()
{
context = lws_create_context( &ctx_info );
if(!context)
return -1;
return 0;
}
int lws_client::connect(int is_ssl_support)
{
char addr_port[256] = { 0 };
sprintf(addr_port, "%s:%u", server_address, port & 65535 );
conn_info = { 0 };
conn_info.context = context;
conn_info.address = server_address;
conn_info.port = port;
if(!is_ssl_support)
conn_info.ssl_connection = 0;
else
conn_info.ssl_connection = 1;
conn_info.path = "./";
conn_info.host = addr_port;
conn_info.origin = addr_port;
conn_info.protocol = protocols[ 0 ].name;
wsi = lws_client_connect_via_info( &conn_info );
if(!wsi)
return -1;
return 1;
}
int lws_client::run(int wait_time)
{
lws_service( context, wait_time );
lws_callback_on_writable( wsi );
}
void lws_client::destroy()
{
lws_context_destroy(context);
}
#ifndef __LWS_CLIENT_H__
#define __LWS_CLIENT_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif
#include "libwebsockets.h"
class lws_client
{
private:
char *server_address;
int port;
public:
lws_client(char *lws_server_address,int port);
~lws_client();
lws_client(const lws_client &obj);
void init();
int set_ssl(const char* ca_filepath,
const char* server_cert_filepath,
const char*server_private_key_filepath,
bool is_support_ssl);
int create();
int connect(int is_ssl_support);
int run(int wait_time);
void destroy();
};
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)