Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C libuv简单发送udp_C_Udp_Libuv - Fatal编程技术网

C libuv简单发送udp

C libuv简单发送udp,c,udp,libuv,C,Udp,Libuv,我正在用C编写一个多平台共享库,它使用libuv发送UDP消息,但是我对libuv知之甚少,也不知道我的实现是否良好,或者除了libuv之外是否还有其他解决方案 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <uv.h> #define IP "0.0.0.0" #define PORT 8090 #define STR_BUFFER 2

我正在用C编写一个多平台共享库,它使用libuv发送UDP消息,但是我对libuv知之甚少,也不知道我的实现是否良好,或者除了libuv之外是否还有其他解决方案

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

#define IP "0.0.0.0"
#define PORT 8090
#define STR_BUFFER 256

void on_send(uv_udp_send_t *req, int status) {
    if (status) {
        fprintf(stderr, "Send error %s\n", uv_strerror(status));
        return;
    }
}

int send_udp(char *msg){
    uv_loop_t *loop = malloc(sizeof(uv_loop_t));
    uv_loop_init(loop);
    
    uv_udp_t send_socket;
    uv_udp_init(loop, &send_socket);
    
    struct sockaddr_in send_addr;
    uv_ip4_addr(IP, PORT, &send_addr);
    
    uv_udp_bind(&send_socket, (const struct sockaddr*)&send_addr, 0);

    char buff[STR_BUFFER];
    memset(buff,0,STR_BUFFER);
    strcpy(buff,msg);

    uv_buf_t buffer = uv_buf_init(buff,STR_BUFFER);
    
    uv_udp_send_t send_req;
    uv_udp_send(&send_req, &send_socket, &buffer, 1, (const struct sockaddr*)&send_addr, on_send);
    
    uv_run(loop, UV_RUN_ONCE);
    
    uv_loop_close(loop);
    free(loop);
    
    return 0;
}

int main() {
    send_udp("test 123\n");
    return 0;
}
#包括
#包括
#包括
#包括
#定义IP“0.0.0.0”
#定义端口8090
#定义STR_缓冲区256
发送时无效(uv\U udp\U发送请求,int状态){
如果(状态){
fprintf(标准,“发送错误%s\n”,uv_strerror(状态));
返回;
}
}
int send_udp(字符*msg){
uv_loop_t*loop=malloc(sizeof(uv_loop_t));
uv_loop_init(循环);
uv_udp_t发送_套接字;
uv_udp_init(循环和发送_套接字);
发送地址中的结构sockaddr\u;
uv_ip4_地址(IP、端口和发送地址);
uv_udp_绑定(&send_socket,(const struct sockaddr*)&send_addr,0);
字符buff[STR_BUFFER];
memset(buff,0,STR_缓冲区);
strcpy(浅黄色,味精);
uv_buf_t buffer=uv_buf_init(buff,STR_buffer);
uv_udp_发送_t发送_请求;
uv_udp_send(&send_req,&send_socket,&buffer,1,(const struct sockaddr*)和send_addr,on_send);
uv_运行(循环,uv_运行一次);
uv_回路_闭合(回路);
自由(循环);
返回0;
}
int main(){
发送udp(“测试123\n”);
返回0;
}

到目前为止,您的实施存在多个问题:

  • 我不确定单个循环迭代是否足以在每个平台上发送UDP消息。使用
    uv\u运行一次
    模式时,您可以使用
    uv\u运行
    返回的值轻松检查这一点:
  • UV\u运行一次
    :轮询i/o一次。请注意,如果没有挂起的回调,则此函数将阻塞。完成时返回零(没有剩余的活动句柄或请求),或者如果需要更多回调,则返回非零(这意味着您应该在将来某个时候再次运行事件循环)

    如果您希望代码保持原样,我建议您至少执行以下操作:

    int完成;
    做{
    完成=uv_运行(循环,uv_运行一次);
    }while(完成!=0);
    
    但是继续读下去,你可以做得更好

  • 它的性能非常昂贵,
    uv_循环
    s应该是持久的,而不是为每个发送的消息创建
  • 错误处理不完整:
    uv\u udp\u bind
    uv\u udp\u send
    。。。他们可能会失败 如何改进 我建议您更改以下两种解决方案之一的代码:

    • 您的库是在libuv上下文中使用的(也就是说,您不会试图隐藏libuv实现细节,而是要求所有希望使用您的库的人明确使用libuv。
      然后,您可以将函数签名更改为
      int send\u udp(uv\u loop\u t*loop,char*msg)
      ,并让库用户管理事件循环并运行它

    • 您的库使用libuv作为实现细节:您不想用libuv打扰库用户,因此您有责任提供健壮且性能良好的代码。我将这样做:

      • mylib_init
        :启动线程并在其上运行
        uv_循环
      • send_udp
        :将消息推送到队列上(注意线程安全),通知您的循环它有消息要发送(您可以使用
        uv_async
        ),然后您可以使用与您已经使用的代码大致相同的代码发送消息
      • mylibu shutdown
        :停止循环和线程(同样,您可以使用
        uv\u async
        从右线程调用
        uv\u stop
    它看起来是这样的(我没有要测试的编译器,但您将完成大部分工作):

    static uv\u thread\u t thread;//我们的网络线程
    静态uv_循环\u t循环;//线程上运行的循环
    static uv\u async\u t notify\u send;//通知它有消息要发送的线程
    static uv\u async\u t notify\u shutdown;//要通知线程,它必须关闭
    静态队列\u t缓冲区\u队列;//要发送的消息队列
    静态uv_mutex_t buffer_queue_mutex;//从各个线程同步对队列的访问
    静态无效线程输入(无效*arg);
    发送消息时静态无效(uv异步句柄);
    关闭时静态无效(uv异步句柄);
    int mylib_init(){
    //将调用新线程(我们的网络线程)上的线程\u条目
    返回uv\u thread\u create(&thread,thread\u条目,NULL);
    }
    int send_udp(字符*msg){
    uv_互斥锁(缓冲区_队列_互斥锁);
    queue_enqueue(&buffer_queue,strdup(msg));//发送消息后不要忘记释放()
    uv\u异步发送(¬ify\u发送);
    uv_互斥锁_解锁(&buffer_queue_mutex);
    }
    int mylib_关机(){
    //将在循环线程上调用\u shutdown
    uv\u异步\u发送(&通知\u关闭);
    //等待线程停止
    返回uv螺纹连接(&thread);
    }
    静态无效线程\u条目(无效*arg){
    uv_loop_init(&loop);
    uv_互斥体_init_递归(&buffer_queue_mutex);
    uv_async_init(&loop,¬ify_send,on_send_消息);
    uv_async_init(&loop,¬ify_shutdown,on_shutdown);
    uv_run(&loop,uv_run_DEFAULT);//在调用uv_stop之前,此代码不会返回
    uv_互斥体_销毁(&缓冲区_队列_互斥体);
    uv_回路_闭合(&loop);
    }
    发送消息时静态无效(uv异步句柄){
    uv_互斥锁(缓冲区_队列_互斥锁);
    char*msg=NULL;
    //对于队列的每个成员。。。
    while(queue\u dequeue(&buffer\u queue,&msg)==0){
    //创建一个uv\u udp\t,发送消息
    }
    uv_互斥锁_解锁(&buffer_queue_mutex);
    }
    关闭时静态无效(uv异步句柄){
    uv_停止(&循环);
    }
    
    由您自行开发或找到队列实现;)

    用法
    intmain(){
    mylib_init();
    发送udp(“我的超级消息”);
    mylib_shutdown();
    }