[C++] Simple tutorial of libwebsockets library (with source code)

Table of contents

1. Commonly used APIs

2. Server

3. Client

4. Some pits stepped on


1. Commonly used APIs

(1) lws_create_context: Create the opposite of the context, manage ws

        lws_create_context is a function in the libwebsockets library, used to create a WebSocket context. A WebSocket context is a structure that contains all information and status related to WebSocket. Before creating a WebSocket connection, a WebSocket context needs to be created first. The role of the lws_create_context function is to initialize the WebSocket context and return a pointer to the WebSocket context.

(2) lws_context_destroy: Destroy the context object

        lws_context_destroy is a function used to destroy a libwebsockets application context. It frees all resources allocated to the context, including sockets, threads, buffers, etc. After calling this function, the application will no longer be able to use the context, so you should make sure to only call this function when the context is not needed.

(3) lws_client_connect_via_info: connect to the WebSocket server

        lws_client_connect_via_info is a function in libwebsockets library, its role is to establish a client connection through the provided connection information. This function can be used in client applications to connect to the server. 

Specifically, the lws_client_connect_via_info function needs to provide the following information:

1. The name of the connection protocol, such as http, https, websocket, etc.

2. The hostname or IP address of the server.

3. The port number of the server.

4. Connection options, such as SSL/TLS certificates, etc.

5. Callback function for handling connection status and receiving data.

By providing this information, the lws_client_connect_via_info function can establish a client connection, and call the callback function to process the connection status and receive data after the connection is established.

(4) lws_service: process all unprocessed events and data

        In the libwebsockets library, lws_service is a function that handles all unhandled events and data. It runs in an infinite loop, constantly checking for new events or data to process. When new events or data arrive, it calls the corresponding callback function to handle them. The lws_service function is one of the most important functions in the libwebsockets library, which ensures the stability and reliability of the network connection.

(5) lws_callback_on_writable: Set the server to send data to the client

        lws_callback_on_writable is a function in the libwebsockets library, and its meaning is to add a writable callback function of a websocket connection to the event loop. This callback is fired when the connection's network buffer becomes free. This function is usually used to send data in websocket connection. Calling this function can ensure that data is sent immediately when the network buffer is writable, thereby improving network transmission efficiency.

(6) Commonly used structures

    struct lws // websocket connection handle
    struct lws_context // websocket processor
    struct lws_context_creation_info // context parameter
    struct lws_protocols // protocol layer transport handle
    void* m_pUser; // return callback object
    struct lws_client_connect_info // connection parameters

2. Server

Here are the simple steps to write a WebSocket server using libwebsockets:

(1) Install the libwebsockets library: You can download the latest version of the library from the official website (https://libwebsockets.org/).

The libwebsockets library can be installed with the following command:

sudo apt-get install libwebsockets-dev

(2) Create a WebSocket server

Basic steps:

a. Create a libwebsocket_context object that will manage all client connections.

b. Set the protocol and port number of the server.

c. Create a callback function that will handle the message from the client.

d. Start the server and wait for the client to connect.

Handling client connections: When a client connects to the server, you need to write code to handle the connection. This includes authenticating clients, processing messages, and closing connections.

Sending messages: You can use functions in the libwebsocket library to send messages to clients.

Here is the code for a simple WebSocket server:

In the libwebsocket open source library, the meanings of the parameters of the lws_service callback function are as follows:

1. wsi: websocket instance, indicating the websocket connection currently being processed.

2. reason: The reason code for closing the connection. This parameter is 0 if the connection is not closed.

3. user: User data, which can be set using the lws_callback_on_writable function.

4. in: Received data buffer.

5. len: The length of the received data.

6. flags: Flag bits, used to indicate connection status and other information.

7. out: send data buffer.

8. out_len: Send data length.

9. reserved: Reserved parameters, not used temporarily.

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

static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
{
    return 0;
}

static int callback_websocket(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
{
    switch (reason) {
        case LWS_CALLBACK_ESTABLISHED:
            printf("WebSocket connection established\n");
            break;
        case LWS_CALLBACK_RECEIVE:
            printf("Received data: %s\n", (char *)in);
            break;
        case LWS_CALLBACK_CLOSED:
            printf("WebSocket connection closed\n");
            break;
        default:
            break;
    }
    return 0;
}


//注册协议,一种协议,对应一套处理方案(类似驱动中的设备树)
static struct lws_protocols protocols[] = {
    {
        "http",
        callback_http,
        0,
        0,
    },
    {
        "websocket",
        callback_websocket,
        0,
        0,
    },
    { NULL, NULL, 0, 0 } /* end of list */
};

int main(int argc, char **argv)
{
    struct lws_context_creation_info info;
    struct lws_context *context;
    int port = 9000;

    memset(&info, 0, sizeof(info));
    info.port = port;
    info.protocols = protocols;

    context = lws_create_context(&info);

    if (!context) {
        printf("Error creating WebSocket context\n");
        return 1;
    }

    printf("WebSocket server started on port %d\n", port);

    while (1) {
        lws_service(context, 50);
    }

    lws_context_destroy(context);

    return 0;
}

(3) Compile and run the server

The server can be compiled with the following command:

gcc -o server server.c -lwebsockets

Then run the server:
 

./server

Now that the WebSocket server is started, you can connect to it using a browser or other WebSocket client.

The above is a simple tutorial for creating a WebSocket server using the libwebsockets library, I hope it will be helpful to you.

3. Client

(1) Basic steps:

A. Introduce the header file of the libwebsocket library in the code:

#include <libwebsockets.h>

B. Create an lws_context object for managing WebSocket connections:

struct lws_context* context;

C. Define the connection parameter structure and set the connection information:

struct lws_client_connect_via_info connect_info = {
    .context = context,
    .address = "192.168.12.226",
    .port = 8081,
    .path = "/",
    .host = "192.168.12.226",
    .origin = "http://192.168.12.226",
    .protocol = NULL,
    .user = NULL,
    .password = NULL
};

D. Use the lws_client_connect_via_info() function to connect to the WebSocket server:

lws* ws_client = lws_client_connect_via_info(&connect_info);

E. After the connection is successful, you can use the lws_write() function to send a message to the server:

char *message = "Hello, WebSocket Server!";
lws_write(ws_client, (unsigned char *)message, strlen(message), LWS_WRITE_TEXT);

F. Finally, at the end of the program, use the lws_context_destroy() function to release resources:

lws_context_destroy(context);

(2) The following is a sample code for creating a basic WebSocket client using the libwebsockets library:

lws_client_connect_via_info is a function to connect to a WebSocket server with the given connection information. It takes a pointer to a connection information structure as an argument and returns a pointer to a connection handle. The connection info structure contains all necessary information about the connection, such as the server's address, port number, protocol, etc. Use this function to conveniently connect to a WebSocket server and start communicating.

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

static int callback_websocket(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
{
    switch (reason) {
        case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
            fprintf(stderr, "Error connecting to server\n");
            break;
        case LWS_CALLBACK_CLIENT_ESTABLISHED:
            fprintf(stderr, "Connected to server\n");
            break;
        case LWS_CALLBACK_CLIENT_RECEIVE:
            fprintf(stderr, "Received data: %s\n", (char *)in);
            break;
        case LWS_CALLBACK_CLOSED:
            fprintf(stderr, "Disconnected from server\n");
            break;
        default:
            break;
    }

    return 0;
}

int main(int argc, char **argv)
{
    struct lws_context *context;
    struct lws *websocket;
    struct lws_client_connect_info connect_info;

    memset(&connect_info, 0, sizeof(connect_info));
    connect_info.context = context;
    connect_info.address = "localhost";
    connect_info.port = 8000;
    connect_info.path = "/";
    connect_info.host = connect_info.address;
    connect_info.origin = connect_info.address;
    connect_info.protocol = NULL;
    connect_info.ssl_connection = 0;

    struct lws_protocols protocols[] = {
        { "default", callback_websocket, 0, 0 },
        { NULL, NULL, 0, 0 }
    };

    context = lws_create_context(NULL, NULL, protocols, NULL, NULL, NULL, NULL, -1, -1, 0);

    if (context == NULL) {
        fprintf(stderr, "Error creating context\n");
        return 1;
    }

    websocket = lws_client_connect_via_info(&connect_info);

    if (websocket == NULL) {
        fprintf(stderr, "Error connecting to server\n");
        return 1;
    }

    while (lws_service(context, 0) >= 0);

    lws_context_destroy(context);

    return 0;
}

This sample code creates a WebSocket client, connects to localhost on port 8000, and prints any data received. You can change connect_info.address and connect_info.port to connect to other WebSocket servers.

In the main() function, we first set the connection information structure connect_info, and then create a lws_context object. Next, we call lws_client_connect_via_info() to connect to the WebSocket server and use lws_service() in a while loop to process any incoming data or events. Finally, we destroy the lws_context object and return 0, indicating that the program ended successfully.

4. Some pits stepped on

(1) When compiling, an error will be reported saying: the lws-misc.h variable humanize_schema_si in the libwebsocket library has an unknown size.

Solution: Normally, this is not an error when the linux compiler is used, but vs will report an error. It should be caused by the security and syntax checking rules of vs.

So when the windows compiler is used, just change it.

 (2) The name of the client to connect to the server, remember to be consistent with the name of the server, otherwise it will not be able to connect.

Guess you like

Origin blog.csdn.net/bigger_belief/article/details/131111430