admin管理员组

文章数量:1577577

一. udp传输的例子

1. udp 服务器的例子

/*
 libuv udp server
*/
#include <uv.h>
#include <stdio.h>
#include <stdlib.h>

void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
    // Allocate a buffer for receiving data
    buf->base = (char*)malloc(suggested_size);
    buf->len = suggested_size;
}

void on_recv_data(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) {
    if (nread < 0) {
        // Error occurred while receiving data
        fprintf(stderr, "Error: %s\n", uv_strerror(nread));
        free(buf->base);
        return;
    }

    if (nread > 0) {
        // Process the received data
        printf("Received data: %s\n", buf->base);
    }

    free(buf->base);
}

int main() {
    uv_loop_t* loop = uv_default_loop();

    uv_udp_t server;
    uv_udp_init(loop, &server);

    struct sockaddr_in addr;
    uv_ip4_addr("0.0.0.0", 12345, &addr);

    uv_udp_bind(&server, (const struct sockaddr*)&addr, UV_UDP_REUSEADDR);

    uv_udp_recv_start(&server, on_alloc_buffer, on_recv_data);

    return uv_run(loop, UV_RUN_DEFAULT);
}

2. udp 客户端的例子

/*
    libuv udp client
*/
#include <uv.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
int main() {
    uv_loop_t* loop = uv_default_loop();

    uv_udp_t socket;
    uv_udp_init(loop, &socket);

    uv_udp_send_t send_req;
    uv_buf_t buffer;
    const char* message = "Hello, server!";
    buffer = uv_buf_init(const_cast<char*>(message), strlen(message));

    struct sockaddr_in server_addr;
    uv_ip4_addr("127.0.0.1", 12345, &server_addr);

    uv_udp_send(&send_req, &socket, &buffer, 1, (const struct sockaddr*)&server_addr, nullptr);

    uv_run(loop, UV_RUN_DEFAULT);

    uv_loop_close(loop);
    return 0;
}

3. nc命令模拟udp client

二. 代码解析

结构体解析

uv_udp_t

struct uv_udp_s {
  UV_HANDLE_FIELDS
  /* read-only */
  /*
   * Number of bytes queued for sending. This field strictly shows how much
   * information is currently queued.
   */
  size_t send_queue_size;
  /*
   * Number of send requests currently in the queue awaiting to be processed.
   */
  size_t send_queue_count;
  UV_UDP_PRIVATE_FIELDS
};
typedef struct uv_udp_s uv_udp_t;

uv_udp_t 结构体 是用于UDP通信的抽象数据类型。它代表了一个UDP套接字,用于在网络上发送和接收UDP数据包。
uv_udp_t 结构体包含了一系列用于配置和管理UDP套接字的成员变量,以及一系列用于操作UDP套接字的函数。

uv_buf_t

typedef struct uv_buf_t {
  char* base;
  size_t len;
} uv_buf_t;

uv_buf_t 结构体表示一个用于存储数据的缓冲区,通常用于在异步 I/O 操作中传递数据。
包含两个变量:
base:指向存储数据的缓冲区的起始位置的指针。
len:表示缓冲区的长度,即缓冲区中可用于存储数据的字节数。

uv_udp_send_t

struct uv_udp_send_s {
  UV_REQ_FIELDS
  uv_udp_t* handle;
  uv_udp_send_cb cb;
  UV_UDP_SEND_PRIVATE_FIELDS
};
typedef struct uv_udp_send_s uv_udp_send_t;

uv_udp_send_t 结构体代表了一个 UDP 发送请求,用于发送 UDP 数据包。它被用于异步地发送 UDP 数据包到目标地址。

函数解析

uv_udp_init

int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle);
这个函数用于初始化 UDP 套接字,并将其与事件循环关联。
在调用这个函数之后,handle 参数所指向的 uv_udp_t 结构体实例将被初始化,并且可以用于进行 UDP 相关的操作。

uv_ip4_addr

int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr);
这个函数将 IPv4 地址和端口转换为网络字节顺序,并填充到 sockaddr_in 结构体中。

形参解析:
ip:一个字符串,表示 IPv4 地址。可以是点分十进制格式的 IP 地址,也可以是域名(例如:“127.0.0.1” 或 “localhost”)。
port:一个整数,表示端口号。
addr:一个指向 sockaddr_in 结构体的指针,用于存储转换后的 IPv4 地址和端口信息。

uv_udp_bind

int uv_udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int flags);

这个函数是将一个 UDP 套接字绑定到指定的本地地址和端口,以便可以接收和发送数据。

形参解析:
handle:一个指向已初始化的 uv_udp_t 结构体实例的指针,表示要绑定的 UDP 套接字。
addr:一个指向 sockaddr 结构体的指针,表示要绑定的本地地址和端口。
flags:用于指定绑定选项的标志uv_udp_flags

uv_udp_recv_start

int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb);

这个函数用于通知 libuv 开始监听指定 UDP 套接字上的数据包,并指定一个回调函数来处理接收到的数据。

形参解析:
handle:一个指向已初始化的 uv_udp_t 结构体实例的指针,表示要开始接收数据的 UDP 套接字。
alloc_cb:一个回调函数,用于分配内存以存储接收到的数据。它的原型为 void (alloc_cb)(uv_handle_t handle, size_t suggested_size, uv_buf_t* buf)。
recv_cb:一个回调函数,用于处理接收到的数据。它的原型为 void (recv_cb)(uv_udp_t handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags)。

uv_udp_send

int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, const uv_buf_t bufs[], unsigned int nbufs, const struct sockaddr* addr, uv_udp_send_cb send_cb);

这个函数将数据包异步发送到指定的目标地址。
形参解析:
req:一个指向 uv_udp_send_t 结构体实例的指针,表示发送请求。在发送完成后,该结构体将被 libuv 使用来通知发送结果。
handle:一个指向已初始化的 uv_udp_t 结构体实例的指针,表示要使用的 UDP 套接字。
bufs:一个指向 uv_buf_t 结构体数组的指针,表示要发送的数据。每个 uv_buf_t 结构体表示一个数据缓冲区,可以包含一部分要发送的数据。
nbufs:一个无符号整数,表示 bufs 数组中数据缓冲区的数量。
addr:一个指向 sockaddr 结构体的指针,表示要发送数据的目标地址。
send_cb:一个回调函数,用于处理发送结果。它的原型为 void (send_cb)(uv_udp_send_t req, int status)

参考

libuv官方文档

https://libuv-docs-chinese.readthedocs.io/zh/latest/

chatgpt

https://chat.openai/

本文标签: libuvudp