我在使用TCP套接字的C / Linux中有一个聊天服务器。使用libev时,我可以为套接字创建一次ev_io观察器,用于读取事件。类似的东西:
ev_io* new_watcher = (ev_io*)malloc(sizeof(ev_io));
//initialize the watcher
ev_init(new_watcher, read_cb);
//set the fd and event to fire on write
ev_io_set(new_watcher, watcher->fd, EV_READ);
//start watching
ev_io_start(loop, new_watcher);
这样可以正常工作,因为只有在有数据需要读取时才会触发读取事件。但是,我必须区别对待写入事件,因为即使我没有要写入的数据,它们也会不断触发。为了解决这个问题,我的read_callback只有在准备好写入数据时才为写入数据创建一个ev_io观察器,然后write_callback将在发送它的消息后删除观察者。
这意味着每次我需要处理消息时,我都在分配,初始化,设置,观察,取消观看和取消分配写入观察者。我担心我可能会错误地和低效地处理这个问题。
在libev中处理write_callback事件的最佳方法是什么?
提前致谢。
答案 0 :(得分:4)
很简单,还有ev_io_stop,所以你做的不是启动写观察者,除非你有什么要写的,而在回调中,你在写完整个缓冲区时调用ev_io_stop。
在通常情况下,您很少会溢出写入缓冲区(因为您的数据很小并且您不经常使用),您可以通过尝试直接写入数据(如果观察者不活动)来提高效率并且只有在你无法完全写入数据时才缓冲数据并启动写入观察器。
根据上述假设,这意味着您几乎不需要启动写入观察器。缺点是代码要复杂得多,因此在很多情况下,最好从简单的“将数据附加到写入缓冲区,启动观察者,在监视器内部停止,如果缓冲区已完全写入”逻辑开始。
答案 1 :(得分:0)
分配可以增加一些开销,你可以使用一个静态变量而不是malloc,或者malloc一次,只有在事件循环结束后才能释放。 您只需要在写入之前设置并在成功之后取消设置。但是,是的,这就是它需要做的事情。
答案 2 :(得分:0)
我解决这种情况的方法是有一个写入数据的函数,它接受一个指向缓冲区和长度的指针。它将指针和长度存储在队列数据结构中,并启用写事件。
当写入事件回调触发时,它会检查写入队列以查看是否有任何挂起的写入。如果有,则在队列中进行下一个挂起写入并将其写入文件描述符。然后就在写回调退出之前,它会检查挂起的写队列是否为空。如果是这样,那么它会禁用写事件。
如果使您的读/写事件对象成为全局变量,那么它们只会被分配并释放一次。只要知道有要写入的数据,就可以启用写入事件,一旦没有更多数据要写入,就会禁用它。
我的代码比上面的描述复杂一些,但我会在这里发布一个链接,以便你可以看看。我特别谈到的代码是aiofd.h和aiofd.c(aiofd == Asynchronous I / O File Descriptor):https://bitbucket.org/wookie/cutil/
我希望这会有所帮助。