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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

epoll服务器

發布時間:2024/4/11 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 epoll服务器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

下面來看看linux內核具體的epoll機制實現思路。

當某一進程調用epoll_create方法時,Linux內核會創建一個eventpoll結構體,這個結構體中有兩個成員與epoll的使用方式密切相關。eventpoll結構體如下所示:

[cpp]?view plaincopy
  • struct?eventpoll{??
  • ????....??
  • ????/*紅黑樹的根節點,這顆樹中存儲著所有添加到epoll中的需要監控的事件*/??
  • ????struct?rb_root??rbr;??
  • ????/*雙鏈表中則存放著將要通過epoll_wait返回給用戶的滿足條件的事件*/??
  • ????struct?list_head?rdlist;??
  • ????....??
  • };??
  • 每一個epoll對象都有一個獨立的eventpoll結構體,用于存放通過epoll_ctl方法向epoll對象中添加進來的事件。這些事件都會掛載在紅黑樹中,如此,重復添加的事件就可以通過紅黑樹而高效的識別出來(紅黑樹的插入時間效率是lgn,其中n為樹的高度)。

    而所有添加到epoll中的事件都會與設備(網卡)驅動程序建立回調關系,也就是說,當相應的事件發生時會調用這個回調方法。這個回調方法在內核中叫ep_poll_callback,它會將發生的事件添加到rdlist雙鏈表中。

    在epoll中,對于每一個事件,都會建立一個epitem結構體,如下所示:

    [cpp]?view plaincopy
  • struct?epitem{??
  • ????struct?rb_node??rbn;//紅黑樹節點??
  • ????struct?list_head????rdllink;//雙向鏈表節點??
  • ????struct?epoll_filefd??ffd;??//事件句柄信息??
  • ????struct?eventpoll?*ep;????//指向其所屬的eventpoll對象??
  • ????struct?epoll_event?event;?//期待發生的事件類型??
  • }??
  • 當調用epoll_wait檢查是否有事件發生時,只需要檢查eventpoll對象中的rdlist雙鏈表中是否有epitem元素即可。如果rdlist不為空,則把發生的事件復制到用戶態,同時將事件數量返回給用戶。

    epoll數據結構示意圖

    從上面的講解可知:通過紅黑樹和雙鏈表數據結構,并結合回調機制,造就了epoll的高效。

    OK,講解完了Epoll的機理,我們便能很容易掌握epoll的用法了。一句話描述就是:三步曲。

    第一步:epoll_create()系統調用。此調用返回一個句柄,之后所有的使用都依靠這個句柄來標識。

    第二步:epoll_ctl()系統調用。通過此調用向epoll對象中添加、刪除、修改感興趣的事件,返回0標識成功,返回-1表示失敗。

    第三部:epoll_wait()系統調用。通過此調用收集收集在epoll監控中已經發生的事件。

    epoll優點:
    1.epoll維護的描述符數目不受到限制,而且性能不會隨著描述符數目的增加而下降。(不需要遍歷整個文件描述符)
    2.epoll先通過epoll_ctl注冊一個描述符到內核中,并一直維護著而不像poll每次操作都將所有要監控的描述符傳遞給內核
    3.在描述符讀寫就緒時,通過回掉函數將自己加入就緒隊列中,之后epoll_wait返回該就緒隊列,所以用戶不需要遍歷整個文件描述符判斷哪些事件就緒。性能提升。
    4.支持ET高效模式。




    void usage(const char* str )
    ?12 {
    ?13 ? ? printf("usage:[local_IP][local_port]\n",str);
    ?14 }
    ?15?
    ?16 int startup(const char* ip,int port)
    ?17 {
    ?18 ? ? int listen_sock=socket(AF_INET,SOCK_STREAM,0);
    ?19 ? ? if(listen<0){
    ?20 ? ? ? ? perror("sock");
    ?21 ? ? ? ? exit(2);
    ?22 ? ? ? ? }
    ?23 ? ? struct sockaddr_in ?local;
    ?24 ? ? local.sin_family=AF_INET;
    ?25 ? ? local.sin_port=htons(port);
    ?26 ? ? local.sin_addr.s_addr=inet_addr(ip);
    ?27 ? ? if(bind(listen_sock,(struct sockaddr *)&local,sizeof(local))<0){
    ?28 ? ? ? ? perror("bind");
    ?29 ? ? ? ? exit(3);
    ?30 ? ? ? ? }
    ?31 ? ? ? ? if(listen(listen_sock,20)<0){
    ?32 ? ? ? ? ? ? perror("listen");
    ?33 ? ? ? ? ? ? exit(4);
    ?34 ? ? ? ? ? ? }
    ?35 ? ? ? ? ? ? return listen_sock;
    ?36 }
    ?37??int main(int argc,char* argv[])
    ?39 {
    ?40 ? ? if(argc!=3){
    ?41 ? ? ? ? usage(argv[0]);
    ?42 ? ? ? ? exit(1);
    ?43 ? ? ? ? }
    ?44 ? ? ? ? int listen_sock=startup(argv[1],atoi(argv[2]));
    ?45?
    ?46 ? ? ? ? int epollfd=epoll_create(256);
    ?47 ? ? ? ? if(epollfd<0){
    ?48 ? ? ? ? ? ? perror("epoll");
    ?49 ? ? ? ? ? ? close(listen_sock);
    ?50 ? ? ? ? ? ? exit(5);
    ?51 ? ? ? ? ? ? }
    ?52?
    ?53 ? ? ? ? ? ? struct epoll_event ?ev;
    ?54 ? ? ? ? ? ? ev.events=EPOLLIN;
    ?55?
    ?56 ? ? ? ? ? ? int ret=epoll_ctl(epollfd,EPOLL_CTL_ADD,listen_sock,&ev);
    ?57?
    ?58 ? ? ? ? ? ? struct epoll_event evs[64];
    ?59 ? ? ? ? ? ? int timeout=1000;
    ?60 ? ? ? ? ? ? int nums=0;
    ?61?
    ?62 ? ? ? ? ? ? while(1){
    ?63 ? ? ? ? ? ? ? ? switch(nums=epoll_wait(epollfd,evs,64,timeout)){
    ?64 ? ? ? ? ? ? ? ? ? ? case 0:

    64 ? ? ? ? ? ? ? ? ? ? printf("timeout..\n"); ? ? ? ? ?
    ?65 ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? ? ? ??
    ?66 ? ? ? ? ? ? ? ? ? ? case -1: ? ? ? ? ? ? ? ? ? ? ? ? ?
    ?67 ? ? ? ? ? ? ? ? ? ? perror("epollwait"); ? ? ? ? ? ? ??
    ?68 ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
    ?69 ? ? ? ? ? ? ? ? ? ? default:{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
    ?70 ? ? ? ? ? ? ? ? ? ? ? ? int i=0; ? ? ? ? ? ? ? ?
    ?71 ? ? ? ? ? ? ? ? ? ? ? ? for(;i<64;i++){ ? ? ? ? ? ? ? ? ? ? ? ? ??
    ?72 ? ? ? ? ? ? ? ? ? ? ? ? ? ? int sock=evs[i].data.fd; ? ? ? ? ? ? ?
    ?73 ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(sock==listen_sock&&(evs[i].events&EPOLLIN)){
    ?74 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //listen_sock ready;
    ?75 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct sockaddr_in client;
    ?76 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? socklen_t len=sizeof(client);
    ?77 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);
    ?78 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(new_sock<0){ ? ? ? ?
    ?79 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? perror("acceot"); ??
    ?80 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? ?
    ?81 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
    ?82 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ev.events=EPOLLIN;
    ?83 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ev.data.fd=new_sock; ? ? ? ? ?
    ?84 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? epoll_ctl(epollfd,EPOLL_CTL_ADD,new_sock,&evs);
    ?85?85?
    ?86?
    ?87 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }else if(sock!=listen_sock){
    ?88 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(evs[i].events&EPOLLIN){
    ?89 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //normal ready;
    ?90 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? char buf[1024];
    ?91 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ssize_t s=read(sock,buf,sizeof(buf)-1);
    ?92 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(s>0){
    ?93 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("client say# :%s\n",buf);
    ?94 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ev.events=EPOLLOUT;
    ?95 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ev.data.fd=sock;
    ?96 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? epoll_ctl(epollfd,EPOLL_CTL_MOD,sock,&evs);
    ?97 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }else if(s==0){
    ?98 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("client quit\n");
    ?99 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? epoll_ctl(epollfd,EPOLL_CTL_DEL,sock,NULL);
    100 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }else {
    101 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? perror("read");
    102 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? close(sock);
    103 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? epoll_ctl(epollfd,EPOLL_CTL_MOD,sock,&ev);
    104 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
    105 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
    106 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }else {
    107 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(evs[i].events&EPOLLOUT){
    108 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //normal wrute ready
    109 ? ? ? ? ? ? ? ? ? ? ? ? ?const char *msg = "HTTP/1.0 200 OK\r\n\r\n<html><h1> hello epoll!</h1></html>";
    110 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? write(sock,msg,strlen(msg));
    111 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
    112 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 112,6-24 ? ? ?83%
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    總結

    以上是生活随笔為你收集整理的epoll服务器的全部內容,希望文章能夠幫你解決所遇到的問題。

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