Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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语言中面向回调的库的建议_C_Sockets - Fatal编程技术网

C语言中面向回调的库的建议

C语言中面向回调的库的建议,c,sockets,C,Sockets,我正在制作一个小型的库,用C语言控制各种嵌入式设备。我正在使用UDP套接字与每个设备通信。设备向我发送各种有趣的数据、警报和通知,同时发送一些库内部使用但用户可能不感兴趣的数据。所以,我实现了一种回调方法,用户可以在每个设备上注册一个回调函数,其中包含一些有趣的事件。现在,这个库的总体设计是这样的:- 我有两个线程在运行。 在其中一个线程中,有一个无限while事件循环,它使用选择和非阻塞套接字来维护与每个设备的通信。 基本上,每次我从任何设备接收到一个数据包时,我都会去掉包含20字节无用信息的

我正在制作一个小型的库,用C语言控制各种嵌入式设备。我正在使用UDP套接字与每个设备通信。设备向我发送各种有趣的数据、警报和通知,同时发送一些库内部使用但用户可能不感兴趣的数据。所以,我实现了一种回调方法,用户可以在每个设备上注册一个回调函数,其中包含一些有趣的事件。现在,这个库的总体设计是这样的:-

我有两个线程在运行。 在其中一个线程中,有一个无限while事件循环,它使用选择和非阻塞套接字来维护与每个设备的通信。 基本上,每次我从任何设备接收到一个数据包时,我都会去掉包含20字节无用信息的报头,并添加我自己的包含设备ID的报头,请求时间请求被发送来检索该数据包,检索时间现在数据包实际到达时,请求ID和请求类型报警、数据,通知等。。。 现在,具有无限循环的线程1将具有新头的数据包放入环形缓冲区,然后通知另一个线程2解析此信息。 在线程2中,当收到通知时,它锁定缓冲区并读取数据包并开始解析它。 每一条消息都包含一些用户可能不感兴趣的信息,所以我提供了用户回调方法来处理对用户有用的数据。 基本上,我在线程2中做了类似的事情:-

线程2

wait(data_put_in_buffer_cond)

lock(buffer_mutex)

packet_t* packet = pop_packet_from_buffer(buf);

unlock(buffer_mutex)

/* parsing the package... */
parsed_packet_t* parsed_packet = parse_and_change_endianess(packet->data);
/* header for put by thread #1 with host byte order only not parsing necessary */
header_t* header = get_header(packet);

/* thread 1 sets free callback for kind of packet it puts in buffer 
 * This not a critical section section of buffer, so fine without locks
 */
buffer.free_callback(packet);

foreach attribute in parsed_packet->attribute_list {
   register_info_t* rinfo = USER_REGISTRED_EVENT_TABLE[header->device_id][attribute.attr_id];

   /*user is register with this attribute ID on this device ID */
   if(rinfo != NULL) {
      rinof->callback(packet);
   }

   // Do some other stuff with this attribute..
}
free(parsed_packet);
现在,我关心的是,如果用户实现的回调函数需要一些时间才能完成,同时由于环形缓冲区处于覆盖模式,我可能会丢弃一些数据包,会发生什么情况?我已经在3到4台设备上测试了我的API,如果回调函数等待相当长的时间,我没有看到太多的丢弃事件。我推测这种方法可能不是最好的


如果我使用某种线程池来运行用户回调函数,这会是一种更好的设计吗?在这种情况下,在将数据包发送给用户回调之前,我需要创建数据包的显式副本?每个数据包大约有500到700个字节,我每秒从每个设备得到大约2个数据包。任何关于改进当前设计或解决此问题的建议或意见都将不胜感激。

每个设备获得500-700字节根本不是问题,特别是如果您只有3-4个设备。即使你有,比方说,100台设备,这也不是问题。复制开销很可能可以忽略不计。所以,我的建议是:在确定缓冲区复制是您的瓶颈之前,不要尝试预先进行优化


关于丢失数据包,正如您在问题中所说,您已经在使用缓冲环了,我假设这类似于循环队列,对吗?。如果队列已满,则只需使线程1等待,直到队列中有一些可用空间。显然,来自不同设备的更多事件可能会到来,但这不应该是一个问题。一旦您再次拥有空间,选择将让您知道您有来自不同设备的可用数据,因此您只需要处理所有这些数据。当然,为了平衡系统,您可以将队列的大小设置为一个值,以尽可能减少队列已满的次数,因此线程1需要等待。

为什么不添加一个来自设备的消息队列呢?感谢您的回复,我目前正在将消息放入类似队列的循环缓冲区中。感谢您的评论,但我确实需要保持线程1的实时优先级,因为如果没有活动消息以固定的间隔发送给它们,则设备的连接将丢失~500毫秒。包丢失对我来说不太重要,我可以增加环缓冲区大小..但我担心id用户回调函数会花费大量时间并阻止线程2的处理..可能是在某些GUI程序中使用库..其中回调用于更新GUI..如果您不担心丢失数据包,如果队列已满,您可以丢弃数据包,以避免线程1阻塞。在这种情况下,更重要的是选择队列的大小,以使数据包丢失最小化。