【问题标题】:Libuv UDP basic sendLibuv UDP 基本发送
【发布时间】:2026-01-31 17:40:01
【问题描述】:

当我尝试发送一些基本的 UDP 消息时,它看起来好像没有发送它。 我尝试运行我在网上找到的几个示例。 我正在使用 SocketTest v3.0.0 来测试服务器/客户端。 当我测试 TCP 发送时,一切都按预期工作,但在 UDP 情况下,它根本没有。

你能提供一些非常基本的 UDP 发送代码 sn-p 吗? 例如接收者将在本地主机上,并且消息将包含“test”并且它将是固定长度?

还有一个小问题。如果我在本地主机上发送消息,应用程序(服务器)本身是否可以接收它并认为其他人已经发送它(导致循环),因为它没有连接到某个对等点,它只是发送消息并在同一个 ip-port 上侦听?

谢谢:)

【问题讨论】:

  • 你能详细说明什么不起作用吗?你试过什么代码? This test 应该可以帮助您入门。
  • 谢谢,我尝试了几个例子。发送时它返回“0”,因此应该发送它,但没有收到任何消息。我会尝试这些测试。防火墙不应该阻止消息,对吧?
  • uv_udp_send 返回 0 不会收到消息,on_recv 回调的状态说明什么?许多公司防火墙可能会阻止 UDP 流量,您是否尝试过 localhost 来确定?
  • 您提到的测试似乎有效。我尝试了很多其他人......:X。我将举一些例子来结束这个问题。谢谢:)

标签: c libuv


【解决方案1】:

这里有很多有用的例子:https://nikhilm.github.io/uvbook/networking.html

uv_loop_t *loop;
uv_udp_t send_socket;
uv_udp_t recv_socket;

int main() {
    loop = uv_default_loop();

    uv_udp_init(loop, &recv_socket);
    struct sockaddr_in recv_addr;
    uv_ip4_addr("0.0.0.0", 68, &recv_addr);
    uv_udp_bind(&recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
    uv_udp_recv_start(&recv_socket, alloc_buffer, on_read);

    uv_udp_init(loop, &send_socket);
    struct sockaddr_in broadcast_addr;
    uv_ip4_addr("0.0.0.0", 0, &broadcast_addr);
    uv_udp_bind(&send_socket, (const struct sockaddr *)&broadcast_addr, 0);
    uv_udp_set_broadcast(&send_socket, 1);

    uv_udp_send_t send_req;
    uv_buf_t discover_msg = make_discover_msg();

    struct sockaddr_in send_addr;
    uv_ip4_addr("255.255.255.255", 67, &send_addr);
    uv_udp_send(&send_req, &send_socket, &discover_msg, 1, (const struct sockaddr *)&send_addr, on_send);

    return uv_run(loop, UV_RUN_DEFAULT);
}

【讨论】:

    【解决方案2】:

    这是一个基本示例,显示发送 UDP 数据包并接收来自另一端的响应:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <uv.h>
    
    uv_udp_t udp_socket;
    
    void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
      buf->base = malloc(suggested_size);
      buf->len = suggested_size;
    }
    
    void on_read(uv_udp_t *socket, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags){
    
      if (nread < 0) {
        fprintf(stderr, "read error %s\n", uv_err_name(nread));
        uv_close((uv_handle_t*) socket, NULL);
      } else if (nread > 0) {
        char sender[17] = { 0 };
        uv_ip4_name((const struct sockaddr_in*) addr, sender, 16);
        printf("recv from %s:%.*s\n", sender, (int)buf->len, buf->base);
      }
    
      if (buf && buf->base) {
        /* releases the buffer allocated on alloc_buffer() */
        free(buf->base);
      }
    }
    
    void on_send(uv_udp_send_t *req, int status) {
      if (status) {
        fprintf(stderr, "send error %s\n", uv_strerror(status));
      }
      /* releases the request allocated on send_msg() */
      if (req) free(req);
    }
    
    void send_msg(char *msg){
      uv_buf_t buf = uv_buf_init(msg, strlen(msg)+1);
    
      struct sockaddr_in send_addr;
      uv_ip4_addr("123.45.67.89", 2222, &send_addr);
    
      uv_udp_send_t *send_req = malloc(sizeof(uv_udp_send_t));
      uv_udp_send(send_req, &udp_socket, &buf, 1, (const struct sockaddr *)&send_addr, on_send);
    }
    
    int main() {
      uv_loop_t *loop = uv_default_loop();
    
      uv_udp_init(loop, &udp_socket);
      struct sockaddr_in recv_addr;
      uv_ip4_addr("0.0.0.0", 2345, &recv_addr);
      uv_udp_bind(&udp_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
      uv_udp_recv_start(&udp_socket, alloc_buffer, on_read);
    
      send_msg("hi there!");
      send_msg("hello world");
    
      return uv_run(loop, UV_RUN_DEFAULT);
    }
    

    【讨论】:

      【解决方案3】:

      你可以试试stream route handler,虽然是新的,但是很可靠,经过大流量数据交易测试。

      例子

      void read_data(srh_request_t *req);
      void read_data(srh_request_t *req) {
        char *a = "CAUSE ERROR FREE INVALID";
      
        if (strncmp( (char*)req->in_buff->start, "ERROR", 5) == 0) {
          free(a);
        }
        // printf("%d,  %.*s\n", i++, (int) (req->in_buff->end - req->in_buff->start), req->in_buff->start);
        srh_write_output_buffer_l(req, req->in_buff->start, (req->in_buff->end - req->in_buff->start));
        // printf("%d,  %.*s\n", i++, (int) (req->out_buff->end - req->out_buff->start), req->out_buff->start);
      }
      
      int main(void) {
      
        srh_instance_t * instance = srh_create_routing_instance(24, NULL, NULL);
        srh_add_udp_fd(instance, 12345, read_data, 1024, NULL);
        srh_add_tcp_fd(instance, 3232, read_data, 64, NULL);
      
        srh_start(instance, 1);
      
        return 0;
      }
      

      【讨论】: