日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

libev的使用——结合Socket编程

發布時間:2025/3/21 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 libev的使用——结合Socket编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
之前自己學過一些libev編程的基礎,這次寫壓測剛好用上了,才算真正動手寫了些東西,在這里做一些總結。寫這篇文章是為了用淺顯易懂的語言幫助大家做一個入門,我自己也是入門程序媛一只,所以有理解錯誤的地方歡迎指出。

首先推薦幾個我認為學習libev比較好的blog,最后一個地址是官方文檔,給了我很多幫助:

http://vimersu.win/blog/2014/03/06/libev-study/

http://www.cnblogs.com/dirlt/archive/2011/09/07/2169344.html#sec-1

http://blog.csdn.net/woxiaozhi/article/details/16963641

http://www.cnblogs.com/wunaozai/p/3950249.html

http://wenku.baidu.com/link?url=z021OoHoevOJDNP1IVTmEcWvTKRoNKlfzi96k8gUKvcnvdZxlvW4diCihYlxFYRJVjtHSVtYrN451MIqlyznsmO0wUvjRslNPGOZopSIhP_

一.libev原理

  之前簡單寫過一篇libev的學習:http://blog.csdn.net/cxy450019566/article/details/52416349

  有時間可以看看,沒時間直接看這一篇文章。

  需要理解的第一句話:Libev的核心是一個event loop。一個event loop,通俗講就是一個不停在循環運行的事件。

  需要理解的第二句話:Libev通過分配和注冊watcher對不同類型的事件進行監聽,當監聽被觸發時,進行相應的操作。在一個event loop中,我們可以設定對很多libev支持的事件(見上一篇博客)的監聽watcher,這些事件的監聽是異步進行的,觸發任意一個監聽的事件,都可以根據我們的設定進行某些操作。

  理解了這兩句話,你就可以理解libev的作用,以及怎樣來使用libev。

二.通過簡單示例了解libev基本用法

我們從官方示例,來學習libev的基本用法。

[cpp] view plain copy
  • //?libev需要的頭文件??
  • #include?<ev.h>??
  • #include?<stdio.h>??
  • ???
  • //?建立我們剛剛說的需要監聽的事件,這些事件類型是libev提供的??
  • //?with?the?name?ev_TYPE??
  • //ev_io和ev_timer最為常用,ev_io為監聽控制臺輸入,ev_timer為時間事件??
  • ev_io?stdin_watcher;??
  • ev_timer?timeout_watcher;??
  • ???
  • //?以下為自定義的回調函數,當觸發監聽事件時,調用執行對應的函數??
  • ???
  • //?ev_io事件的回調函數,當有輸入流stdin時,調用函數??
  • static?void?stdin_cb?(EV_P_?ev_io?*w,?int?revents)??
  • {??
  • puts?("stdin?ready");??
  • //對ev_io事件的監控不會自動停止,需要手動在需要的時候停止??
  • ev_io_stop?(EV_A_?w);??
  • ???
  • //整體的loop事件在所有監控停止時停止,也可以手動關閉全部的ev_run??
  • ev_break?(EV_A_?EVBREAK_ALL);??
  • }??
  • ???
  • //?時間事件的自定義回調函數,可定時觸發??
  • static?void?timeout_cb?(EV_P_?ev_timer?*w,?intrevents)??
  • {??
  • puts?("timeout");??
  • //關閉最早的一個還在運行的ev_run??
  • ev_break?(EV_A_?EVBREAK_ONE);??
  • }??
  • ???
  • int?main?(void)??
  • {??
  • //定義默認的?event?loop,它就像一個大容器,可以裝載著很多事件不停運行??
  • struct?ev_loop?*loop?=?EV_DEFAULT;??
  • ???
  • //?初始化ev_io事件監控,設置它的回調函數,和stdin??
  • ev_io_init?(&stdin_watcher,?stdin_cb,/*STDIN_FILENO*/?0,?EV_READ);??
  • //將ev_io事件放到event?loop里面運行??
  • ev_io_start?(loop,?&stdin_watcher);??
  • ???
  • //?初始化ev_timer事件監控,設置它的回調函數,間隔時間,是否重復??
  • ev_timer_init?(&timeout_watcher,?timeout_cb,?5.5,0.);??
  • //將ev_timer事件放到event?loop里面運行??
  • ev_timer_start?(loop,?&timeout_watcher);??
  • ???
  • //?將我們的大容器event?loop整體運行起來??
  • ev_run?(loop,?0);??
  • ???
  • //?ev_run運行結束之后,才會運行到這里??
  • return?0;??
  • }??

  • 通過上面的例子,就可以知道libev使用的思路:

    首先,定義一個eventloop大容器 struct ev_loop,和想要的監控事件ev_XXX。

    其次,初始化想要監控的事件,設置好回調函數和相應的參數ev_XXX_init 。

    接下來,讓想要監控的事件都投身到大容器中ev_XXX_start。

    最后,讓大容器帶著小容器一起運行起來 ev_run 。

    ?

    三.常用函數詳解

    1.event loop 相關

    (1)從創建說起:

    我們默認使用EV_DEFAULT類型的loop,使用一下語句來創建:struct ev_loop *loop = EV_DEFAULT;

    EV_DEFAULT宏是以下指令:

    ev_default_loop(EVBACKEND_POLL | EVBACKEND_SELECT | EVFLAG_NOENV);

    返回一個最基礎的ev_loop,并自動完成它的初始化,注意,如果程序中已經執行過該創建,將直接返回之前的創建。除此之外,更多自定義loop,可以使用該函數:struct ev_loop*ev_loop_new (unsigned int flags)。

    (2)讓ev_loop運行起來

    使用函數ev_run(loop, int flags)。

    這里解釋一下flags的作用,用于設置ev_loop的運行方式:

    通常設置為0,表示該ev_loop在所有watcher結束后停止,也可以手動break,官方鼓勵手動break。

    除了0之外,還有一些選擇,如EVRUN_NOWAIT、EVRUN_ONCE。具體請看官方文檔。

    ev_run函數的源碼說明。推薦博文:http://www.cnblogs.com/xiangshancuizhu/archive/2013/08/10/3250558.html

    (3)ev_loop的停止

    前面已經說過,在flags設置為0的情況下,停止主要靠全部watcher停止或者手動break。

    手動break用以下函數:ev_break (loop,how)

    其中,how代表停止的方式:

    EVBREAK_ONE:停止最久遠的那個ev_run

    EVBREAK_ALL:停止所有的ev_run

    2.ev_TYPE公共基礎

    (1)watcher對應的幾種狀態

       initialiased:調用init函數初始化

       active:調用start進行注冊

       pending:已經觸發事件但是沒有處理

       inactive:調用stop注銷。這個狀態等同于initialised這個狀態。

    (2)ev_TYPE對應不同類型的時間監控,共有的標準化函數主要如下:

    [cpp] view plain copy
  • typedef?void?(*)(struct?ev_loop?*loop,?ev_TYPE*watcher,?int?revents)?callback;?//?回調函數都是這種類型??
  • ev_init?(ev_TYPE?*watcher,?callback);?//?初始化watcher??
  • ev_TYPE_set?(ev_TYPE?*watcher,?[args]);?//?設置watcher??
  • ev_TYPE_init?(ev_TYPE?*watcher,?callback,?[args]);?//?這個函數綜合了前兩個函數功能??
  • ev_TYPE_start?(loop,?ev_TYPE?*watcher);?//?在ev_loop中注冊watcher??
  • ev_TYPE_stop?(loop,?ev_TYPE?*watcher);?//?在ev_loop中注銷watcher??
  • ev_set_priority?(ev_TYPE?*watcher,?int?priority);?//?設置watcher優先級,值域為[-2,2],大而優先??
  • ev_feed_event?(loop,?ev_TYPE?*watcher,?int?revents);//?這個做跨線程通知非常有用,相當于觸發了某個事件。??
  • bool?ev_is_active?(ev_TYPE?*watcher);?//?watcher是否active.??
  • bool?ev_is_pending?(ev_TYPE?*watcher);?//?watcher是否pending.??
  • int?ev_clear_pending?(loop,?ev_TYPE?*watcher);?//?清除watcher?pending狀態并且返回事件??
  • 3.ev_io相關

    (1)ev_io結構

    ev_io用來監聽io事件,當有標準輸入或輸出時,則會觸發事件,執行回調函數。

    [cpp] view plain copy
  • typedef?structev_io??
  • {??
  • EV_WATCHER_LIST?(ev_io)??
  • int?fd;?/*?所監聽io事件的文件描述符(file?descriptor,非負數)?*/??
  • int?events;?/*所監聽的事件,包括EV_READ,?EV_WRITE?或?EV_READ?|?EV_WRITE?*/??
  • }?ev_io;??
  • (2)初始化

    兩種方式:

    方式一:ev_init(ev_TYPE *watcher, callback) ,ev_io_set(ev_io *ev, intfd, int events)

    方式二:ev_io_init(ev_io*ev, callback,int fd, int events)

    即需要設置監聽watcher,回調函數callback,文件描述符fd,監聽的事件events。

    (3)運行和停止

    ev_io_start(EV_P_ev_io * w):綁定到ev_loop上

    ev_io_stop(EV_P_ev_io * w):從ev_loop上撤離

    4.ev_timer相關

    (1)ev_timer結構

    ev_timer是一個相對時間的定時器,會在給定的時間點觸發事件,還可以在固定的時間間隔之后再次觸發超時事件。

    [cpp] view plain copy
  • typedef?structev_timer??
  • {??
  • int?active;??
  • int?pending;??
  • int?priority;?/*優先級?*/??
  • void?*data;?/*?參數*/??
  • void?(*cb)(struct?ev_loop?*loop,?struct?ev_timer?*w,int?revents);?/*回調函數?*/??
  • ev_tstamp?at;?/*?定時器時間,單位為s*/??
  • ev_tstamp?repeat;?/*是否重復?*/??
  • }?ev_timer;??
  • (2)初始化

    同樣兩種方式:

    方式一:ev_init(ev_TYPE *watcher, callback) ,ev_timer_set (ev_timer *,ev_tstamp after, ev_tstamp repeat)

    方式二:ev_timer_init(ev_timer *, callback, ev_tstamp after, ev_tstamp repeat)

    即需要設置監聽watcher,回調函數callback,定時器時間after,是否重復repeat。

    其中,repeat設置為0表示定時器只觸發一次,設置為正整數則間隔after秒一直不斷觸發。

    (3)運行和停止

    ev_timer_start(EV_P_ev_io * w):綁定到ev_loop上

    ev_timer_stop(EV_P_ev_io * w):從ev_loop上撤離

    (4)其它函數

    ev_timer_again(loop, ev_timer *) :重啟,對于不同狀態的timer效果不同。

    ev_tstampev_timer_remaining (loop, ev_timer *):返回現在到下一次觸發定時器之間的時間。

    四.在Socket編程的應用實例

    libev用在Socket編程上有幾個好處,用ev_timer可以控制發送頻率,用ev_io可以方便地異步進行包的接收。下面的實例就實現的這個流程,直接用代碼解釋了:

    [cpp] view plain copy
  • double?time_span?=?1.0;?//發送消息的時間間隔??
  • int?test_num?=?5;?//發送消息的次數??
  • int?send_num?=?0;?//已發送消息的次數??
  • int?rev_num?=?0;?//已收到回復的次數??
  • int?fd?=?-1;?//文件描述符??
  • ???
  • struct?ev_loop?*loop?=?EV_DEFAULT;??
  • ev_io?io_watcher;??
  • ev_timer?timer_watcher;??
  • ???
  • //ev_io的回調函數,用于異步接受回復??
  • void?io_action(struct?ev_loop?*main_loop,ev_io*io_w,int?e)??
  • {??
  • char?buf[4096];??
  • char?*ptr?=?(char?*)buf;??
  • int?ret?=?0;??
  • //接收消息??
  • ret?=?::recv(fd,?ptr,?4096,?0);??
  • ???
  • std::cout?<<?buf?<<?"\n";??
  • ???
  • //接收到所有消息,停止ev_io事件??
  • if(rev_num?>=?test_num){??
  • ev_io_stop(main_loop,io_w);??
  • }??
  • }??
  • ???
  • //ev_timer的回調函數,用于定時發送消息??
  • void?timer_action(struct?ev_loop?*main_loop,ev_timer*time_w,int?e)??
  • {??
  • int?ret;??
  • std::string?msg_send?=?"send?msg";??
  • //發送消息??
  • ret?=?::send(fd,?msg_send.c_str(),strlen(msg_send.c_str()),?0);??
  • std::cout?<<?msg_send?<<?"\n";??
  • ???
  • //發送足夠數量的消息后,停止事件??
  • if(send_num?>=?test_num){??
  • ev_timer_stop(main_loop,time_w);??
  • }??
  • }??
  • ???
  • int?main(int?argc,?char?*argv[])??
  • {??
  • fd?=?socket(AF_INET,?SOCK_STREAM,?0);??
  • ret?=?::connect(fd,?(struct?sockaddr?*)&addr,sizeof(addr));??
  • ???
  • ev_init(&io_watcher,io_action);??
  • ev_io_set(&io_watcher,fd,EV_READ);??
  • ???
  • ev_init(&timer_watcher,timer_action);??
  • ev_timer_set(&timer_watcher,time_span,1);??
  • ???
  • ev_io_start(loop,&io_watcher);??
  • ev_timer_start(loop,&timer_watcher);??
  • ???
  • ev_run(loop,0);??
  • return?0;??
  • }??


  • 總結

    以上是生活随笔為你收集整理的libev的使用——结合Socket编程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。