gpt4 book ai didi

c - 重新连接用 C 编写的 websocket 客户端

转载 作者:太空宇宙 更新时间:2023-11-04 01:23:57 26 4
gpt4 key购买 nike

我有一个 websocket 客户端,用 C 写的 libwebsockets图书馆。对于测试,我使用 simple-websocket-server在聊天模式下。

$ python SimpleExampleServer.py —example chat

当发生与 ws-server 的断开连接(如果 ws-server 正在关闭)并等待可能连接到 ws-server,如果客户端比 ws-server 更早启动,我如何编写重新连接客户端。

这是发送和接收消息的客户端源:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <libwebsockets.h>


#define KGRN "\033[0;32;32m"
#define KCYN "\033[0;36m"
#define KRED "\033[0;32;31m"
#define KYEL "\033[1;33m"
#define KBLU "\033[0;32;34m"
#define KCYN_L "\033[1;36m"
#define KBRN "\033[0;33m"
#define RESET "\033[0m"

static int destroy_flag = 0;
static int connection_flag = 0;
static int writeable_flag = 0;

static void INT_HANDLER(int signo) {
destroy_flag = 1;
}

struct session_data {
int fd;
};

struct pthread_routine_tool {
struct lws_context *context;
struct lws *wsi;
};

static int websocket_write_back(struct lws *wsi_in, char *str, int str_size_in)
{
if (str == NULL || wsi_in == NULL)
return -1;

int n;
int len;
char *out = NULL;

if (str_size_in < 1)
len = strlen(str);
else
len = str_size_in;

out = (char *)malloc(sizeof(char)*(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING));
//* setup the buffer*/
memcpy (out + LWS_SEND_BUFFER_PRE_PADDING, str, len );
//* write out*/
n = lws_write(wsi_in, out + LWS_SEND_BUFFER_PRE_PADDING, len, LWS_WRITE_TEXT);

printf(KBLU"[websocket_write_back] %s\n"RESET, str);
//* free the buffer*/
free(out);

return n;
}


static int ws_service_callback(
struct lws *wsi,
enum lws_callback_reasons reason, void *user,
void *in, size_t len)
{

switch (reason) {

case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf(KYEL"[Main Service] Connect with server success.\n"RESET);
connection_flag = 1;
break;

case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
printf(KRED"[Main Service] Connect with server error.\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;

case LWS_CALLBACK_CLOSED:
printf(KYEL"[Main Service] LWS_CALLBACK_CLOSED\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;

case LWS_CALLBACK_CLIENT_RECEIVE:
printf(KCYN_L"[Main Service] Client recvived:%s\n"RESET, (char *)in); //print recive message

// if (writeable_flag)
// destroy_flag = 1;

break;
case LWS_CALLBACK_CLIENT_WRITEABLE :
printf(KYEL"[Main Service] On writeable is called. send byebye message\n"RESET);
websocket_write_back(wsi, "Byebye! See you later", -1);
writeable_flag = 1;
break;

default:
break;
}

return 0;
}

static void *pthread_routine(void *tool_in)
{
struct pthread_routine_tool *tool = tool_in;

printf(KBRN"[pthread_routine] Good day. This is pthread_routine.\n"RESET);

//* waiting for connection with server done.*/
while(!connection_flag)
usleep(1000*20);

//*Send greeting to server*/
printf(KBRN"[pthread_routine] Server is ready. send a greeting message to server.\n"RESET);
websocket_write_back(tool->wsi, "Good day", -1);

printf(KBRN"[pthread_routine] sleep 2 seconds then call onWritable\n"RESET);
sleep(1);
printf(KBRN"------------------------------------------------------\n"RESET);
sleep(1);
//printf(KBRN"[pthread_routine] sleep 2 seconds then call onWritable\n"RESET);

//*involked wriable*/
printf(KBRN"[pthread_routine] call on writable.\n"RESET);
lws_callback_on_writable(tool->wsi);

}

int main(void)
{
//* register the signal SIGINT handler */
struct sigaction act;
act.sa_handler = INT_HANDLER;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction( SIGINT, &act, 0);


struct lws_context *context = NULL;
struct lws_context_creation_info info;
struct lws *wsi = NULL;
struct lws_protocols protocol;

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 = lws_get_internal_extensions();
info.gid = -1;
info.uid = -1;
info.options = 0;

protocol.name = "my-echo-protocol";
protocol.callback = &ws_service_callback;
protocol.per_session_data_size = sizeof(struct session_data);
protocol.rx_buffer_size = 0;
protocol.id = 0;
protocol.user = NULL;

context = lws_create_context(&info);
printf(KRED"[Main] context created.\n"RESET);

if (context == NULL) {
printf(KRED"[Main] context is NULL.\n"RESET);
return -1;
}


wsi = lws_client_connect(context, "localhost", 8000, 0,
"/", "localhost:8000", NULL,
protocol.name, -1);
if (wsi == NULL) {
printf(KRED"[Main] wsi create error.\n"RESET);
return -1;
}

printf(KGRN"[Main] wsi create success.\n"RESET);

struct pthread_routine_tool tool;
tool.wsi = wsi;
tool.context = context;

pthread_t pid;
pthread_create(&pid, NULL, pthread_routine, &tool);
pthread_detach(pid);

while(!destroy_flag)
{
lws_service(context, 50);
}

lws_context_destroy(context);

return 0;
}

最佳答案

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
//#include <libwebsockets.h>
#include "libwebsockets.h"

#define KGRN "\033[0;32;32m"
#define KCYN "\033[0;36m"
#define KRED "\033[0;32;31m"
#define KYEL "\033[1;33m"
#define KBLU "\033[0;32;34m"
#define KCYN_L "\033[1;36m"
#define KBRN "\033[0;33m"
#define RESET "\033[0m"

static int destroy_flag = 0;
static int connection_flag = 0;
static int writeable_flag = 0;

static void INT_HANDLER(int signo) {
destroy_flag = 1;
}

struct session_data {
int fd;
};

struct pthread_routine_tool {
struct lws_context *context;
struct lws *wsi;
};

static int websocket_write_back(struct lws *wsi_in, char *str, int str_size_in)
{
if (str == NULL || wsi_in == NULL)
return -1;

int n;
int len;
char *out = NULL;

if (str_size_in < 1)
len = strlen(str);
else
len = str_size_in;

out = (char *)malloc(sizeof(char)*(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING));
//* setup the buffer*/
memcpy (out + LWS_SEND_BUFFER_PRE_PADDING, str, len );
//* write out*/
n = lws_write(wsi_in, out + LWS_SEND_BUFFER_PRE_PADDING, len, LWS_WRITE_TEXT);

printf(KBLU"[websocket_write_back] %s\n"RESET, str);
//* free the buffer*/
free(out);

return n;
}


static int ws_service_callback(
struct lws *wsi,
enum lws_callback_reasons reason, void *user,
void *in, size_t len)
{

switch (reason) {

case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf(KYEL"[Main Service] Connect with server success.\n"RESET);
connection_flag = 1;
break;

case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
printf(KRED"[Main Service] Connect with server error.\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;

case LWS_CALLBACK_CLOSED:
printf(KYEL"[Main Service] LWS_CALLBACK_CLOSED\n"RESET);
destroy_flag = 1;
connection_flag = 0;
break;

case LWS_CALLBACK_CLIENT_RECEIVE:
printf(KCYN_L"[Main Service] Client recvived:%s\n"RESET, (char *)in);

// if (writeable_flag)
// destroy_flag = 1;

break;
case LWS_CALLBACK_CLIENT_WRITEABLE :
printf(KYEL"[Main Service] On writeable is called. send byebye message\n"RESET);
websocket_write_back(wsi, "Byebye! See you later", -1);
writeable_flag = 1;
break;

default:
break;
}

return 0;
}

static void *pthread_routine(void *tool_in)
{
struct pthread_routine_tool *tool = tool_in;

printf(KBRN"[pthread_routine] Good day. This is pthread_routine.\n"RESET);

//* waiting for connection with server done.*/
while(!connection_flag)
usleep(1000*20);

//*Send greeting to server*/
printf(KBRN"[pthread_routine] Server is ready. send a greeting message to server.\n"RESET);
websocket_write_back(tool->wsi, "Good day", -1);

printf(KBRN"[pthread_routine] sleep 2 seconds then call onWritable\n"RESET);
sleep(1);
printf(KBRN"------------------------------------------------------\n"RESET);
sleep(1);
//printf(KBRN"[pthread_routine] sleep 2 seconds then call onWritable\n"RESET);

//*involked wriable*/
printf(KBRN"[pthread_routine] call on writable.\n"RESET);
lws_callback_on_writable(tool->wsi);

}

int RUN(void)
{
//* register the signal SIGINT handler */
struct sigaction act;
act.sa_handler = INT_HANDLER;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction( SIGINT, &act, 0);


struct lws_context *context = NULL;
struct lws_context_creation_info info;
struct lws *wsi = NULL;
struct lws_protocols protocol;

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 = lws_get_internal_extensions();
info.gid = -1;
info.uid = -1;
info.options = 0;

protocol.name = "my-echo-protocol";
protocol.callback = &ws_service_callback;
protocol.per_session_data_size = sizeof(struct session_data);
protocol.rx_buffer_size = 0;
protocol.id = 0;
protocol.user = NULL;

context = lws_create_context(&info);
printf(KRED"[Main] context created.\n"RESET);

if (context == NULL) {
printf(KRED"[Main] context is NULL.\n"RESET);
return -1;
}


wsi = lws_client_connect(context, "localhost", 8000, 0,
"/", "localhost:8000", NULL,
protocol.name, -1);
if (wsi == NULL) {
printf(KRED"[Main] wsi create error.\n"RESET);
return -1;
}

printf(KGRN"[Main] wsi create success.\n"RESET);

struct pthread_routine_tool tool;
tool.wsi = wsi;
tool.context = context;

pthread_t pid;
pthread_create(&pid, NULL, pthread_routine, &tool);
pthread_detach(pid);

while(!destroy_flag)
{
lws_service(context, 50);
}
lws_context_destroy(context);
destroy_flag = 0; // new ws not destroyed
pthread_cancel(pid); // kill old thread

return 0;
}

int main()
{

while(!RUN())
{
usleep(1000 * 200);
}
}

关于c - 重新连接用 C 编写的 websocket 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35136902/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com