重新连接用 C 语言编写的 websocket 客户端



我有一个websocket客户端,用C语言编写,带有libwebsockets库。对于测试,我在聊天模式下使用简单的websocket服务器。

$ python SimpleExampleServer.py —example chat

当与 ws-服务器断开连接(如果 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 "33[0;32;32m"
#define KCYN "33[0;36m"
#define KRED "33[0;32;31m"
#define KYEL "33[1;33m"
#define KBLU "33[0;32;34m"
#define KCYN_L "33[1;36m"
#define KBRN "33[0;33m"
#define RESET "33[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] %sn"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_CLOSEDn"RESET);
            destroy_flag = 1;
            connection_flag = 0;
            break;
        case LWS_CALLBACK_CLIENT_RECEIVE:
            printf(KCYN_L"[Main Service] Client recvived:%sn"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 messagen"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 onWritablen"RESET);
    sleep(1);
    printf(KBRN"------------------------------------------------------n"RESET);
    sleep(1);
    //printf(KBRN"[pthread_routine] sleep 2 seconds then call onWritablen"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 "33[0;32;32m"
#define KCYN "33[0;36m"
#define KRED "33[0;32;31m"
#define KYEL "33[1;33m"
#define KBLU "33[0;32;34m"
#define KCYN_L "33[1;36m"
#define KBRN "33[0;33m"
#define RESET "33[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] %sn"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_CLOSEDn"RESET);
            destroy_flag = 1;
            connection_flag = 0;
            break;
        case LWS_CALLBACK_CLIENT_RECEIVE:
            printf(KCYN_L"[Main Service] Client recvived:%sn"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 messagen"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 onWritablen"RESET);
    sleep(1);
    printf(KBRN"------------------------------------------------------n"RESET);
    sleep(1);
    //printf(KBRN"[pthread_routine] sleep 2 seconds then call onWritablen"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);
    }
}

相关内容

  • 没有找到相关文章

最新更新