日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內(nèi)最全IT社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > 綜合技術(shù) > TCP/IP網(wǎng)絡(luò)編程 基于Linux編程_這個優(yōu)于select的epoll

TCP/IP網(wǎng)絡(luò)編程 基于Linux編程_這個優(yōu)于select的epoll

來源:程序員人生   發(fā)布時間:2016-04-06 08:43:27 閱讀次數(shù):5266次

前言:關(guān)于并發(fā)服務(wù)器中的I/O復(fù)用實現(xiàn)方式,前面我們講過select的方式,但select的性能比較低,其實不合適以Web服務(wù)器端開發(fā)為主流的現(xiàn)代開發(fā)環(huán)境。因此就有了Linux下的epoll,BSD的kqueue,Solaris的/dev/poll和Windows的IOCP等復(fù)用技術(shù)。本章就來說講Linux下的epoll技術(shù)。

epoll理解及利用

  • 基于select的I/O復(fù)用技術(shù)速度慢的緣由:
    1,調(diào)用select函數(shù)后常見的針對所有文件描寫符的循環(huán)語句。它每次事件產(chǎn)生需要遍歷所有文件描寫符,找動身生變化的文件描寫符。(之前寫的示例沒加循環(huán))

    2,每次調(diào)用select函數(shù)時都需要向該函數(shù)傳遞監(jiān)視對象信息。即每次調(diào)用select函數(shù)時向操作系統(tǒng)傳遞監(jiān)視對象信息,至于為何要傳?是由于我們監(jiān)視的套接字變化的函數(shù),而套接字是操作系統(tǒng)管理的。(這個才是最耗效力的)

    注釋:基于這樣的緣由其實不是說select就沒用了,在這樣的情況下就合適選用select:1,服務(wù)端接入者少 2,程序應(yīng)具有兼容性。

  • epoll是怎樣優(yōu)化select問題的:
    1,每次產(chǎn)生事件它不需要循環(huán)遍歷所有文件描寫符,它把產(chǎn)生變化的文件描寫符單獨集中到了1起。

    2,僅向操作系統(tǒng)傳遞1次監(jiān)視對象信息,監(jiān)視范圍或內(nèi)容產(chǎn)生變化時只通知產(chǎn)生變化的事項。

  • 實現(xiàn)epoll時必要的函數(shù)和結(jié)構(gòu)體

    函數(shù):
    epoll_create:創(chuàng)建保存epoll文件描寫符的空間,該函數(shù)也會返回文件描寫符,所以終止時,也要調(diào)用close函數(shù)。(創(chuàng)建內(nèi)存空間)

    epoll_ctl:向空間注冊,添加或修改文件描寫符。(注冊監(jiān)聽事件)

    epoll_wait:與select函數(shù)類似,等待文件描寫符產(chǎn)生變化。(監(jiān)聽事件回調(diào))

    結(jié)構(gòu)體:
    struct epoll_event
    {
    __uint32_t events;
    epoll_data_t data;
    }

    typedef union epoll_data
    {
    void *ptr;
    int fd;
    __uinit32_t u32;
    __uint64_t u64;
    } epoll_data_t;

    基于epoll的回聲服務(wù)器

// // main.cpp // hello_server // // Created by app05 on 15⑴0⑴9. // Copyright (c) 2015年 app05. All rights reserved. // #include #include #include #include #include #include #include #define BUF_SIZE 100 #define EPOLL_SIZE 50 void error_handling(char *buf); int main(int argc, const char * argv[]) { int serv_sock, clnt_sock; struct sockaddr_in serv_adr, clnt_adr; socklen_t adr_sz; int str_len, i; char buf[BUF_SIZE]; //類似select的fd_set變量查看監(jiān)視對象的狀態(tài)變化,epoll_event結(jié)構(gòu)體將產(chǎn)生變化的文件描寫符單獨集中到1起 struct epoll_event *ep_events; struct epoll_event event; int epfd, event_cnt; if(argc != 2) { printf("Usage: %s", argv[0]); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); if(serv_sock == -1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); serv_adr.sin_port = htons(atoi(argv[1])); if(bind(serv_sock, (struct sockaddr *) &serv_adr, sizeof(serv_adr)) == -1) error_handling("bind() error"); if(listen(serv_sock, 5) == -1) error_handling("listen() error"); //創(chuàng)建文件描寫符的保存空間稱為“epoll例程” epfd = epoll_create(EPOLL_SIZE); ep_events = malloc(sizeof(struct epoll_event) *EPOLL_SIZE); //添加讀取事件的監(jiān)視(注冊事件) event.events = EPOLLIN; //讀取數(shù)據(jù)事件 event.data.fd = serv_sock; epoll_ctl(epdf, EPOLL_CTL_ADD, serv_sock, &event); while (1) { //響應(yīng)事件,返回產(chǎn)生事件的文件描寫符數(shù) event_cnt = epoll_wait(epfd, ep_events, EPOLL_SIZE, -1); //傳⑴時,1直等待直到事件產(chǎn)生 if(event_cnt == -1) { puts("epoll_wait() error"); break; } //服務(wù)端套接字和客服端套接字 for (i = 0; i < event_cnt; i++) { if(ep_events[i].data.fd == serv_sock)//服務(wù)端與客服端建立連接 { adr_sz = sizeof(clnt_adr); clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_adr, &adr_sz); event.events = EPOLLIN; event.data.fd = clnt_sock; epoll_ctl(epfd, EPOLL_CTL_ADD, clnt_sock, &event); printf("connected client: %d ", clnt_sock); } else //連接以后傳遞數(shù)據(jù) { str_len = read(ep_events[i].data.fd, buf, BUF_SIZE); if(str_len == 0) { //刪除事件 epoll_ctl(epfd, EPOLL_CTL_DEL, ep_events[i].data.fd, NULL); close(ep_events[i].data.fd); printf("closed client: %d ", ep_events[i].data.fd); } else { write(ep_events[i].data.fd, buf, str_len); } } } } close(serv_sock); close(epfd); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc(, stderr); exit(1); }

條件觸發(fā)和邊沿觸發(fā)

  • 甚么是條件觸發(fā)和邊沿觸發(fā)?它們是指事件響應(yīng)的方式,epoll默許是條件觸發(fā)的方式。條件觸發(fā)是指:只要輸入緩沖中有數(shù)據(jù)就會1直通知該事件,循環(huán)響應(yīng)epoll_wait。而邊沿觸發(fā)是指:輸入緩沖收到數(shù)據(jù)時僅注冊1次該事件,即便輸入緩沖中還留有數(shù)據(jù),也不會再進行注冊,只響應(yīng)1次。

  • 邊沿觸發(fā)相對條件觸發(fā)的優(yōu)點:可以分離接收數(shù)據(jù)和處理數(shù)據(jù)的時間點,從實現(xiàn)模型的角度看,邊沿觸發(fā)更有可能帶來高性能。

  • 將上面epoll實例改成邊沿觸發(fā):
    1,首先改寫 event.events = EPOLLIN | EPOLLET; (EPOLLIN:讀取數(shù)據(jù)事件 EPOLLET:邊沿觸發(fā)方式)

    2,邊沿觸發(fā)只響應(yīng)1次接收數(shù)據(jù)事件,所以要1次性全部讀取輸入緩沖中的數(shù)據(jù),那末就需要判斷甚么時候數(shù)據(jù)讀取完了?Linux聲明了1個全局的變量:int errno; (error.h中),它能記錄產(chǎn)生毛病時提供額外的信息。這里就能夠用它來判斷是不是讀取完數(shù)據(jù):

str_len = read(...); if(str_len < 0) { if(errno == EAGAIN) //讀取輸入緩沖中的全部數(shù)據(jù)的標(biāo)志 break; }

3,邊沿觸發(fā)方式下,以阻塞方式工作的read&write有可能會引發(fā)服務(wù)真?zhèn)€長時間停頓。所以邊沿觸發(fā)1定要采取非阻塞的套接字?jǐn)?shù)據(jù)傳輸情勢。那末怎樣將套接字的read,write數(shù)據(jù)傳輸情勢修改成非阻塞模式呢?

//fd套接字文件描寫符,將此套接字?jǐn)?shù)據(jù)傳輸模式修改成非阻塞 void setnonblockingmode(int fd) { int flag = fcntl(fd, F_GETFL,0); //得到套接字原來屬性 fcntl(fd, F_SETFL, flag | O_NONBLOCK);//在原有屬性基礎(chǔ)上設(shè)置添加非阻塞模式 }
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 在线观看黄色一级片 | 日韩一级黄色毛片 | 日韩专区在线播放 | 国产欧美精品 | 国产精品一区二区免费 | 精品国产欧美一区二区三区成人 | 久一在线视频 | 亚洲国产成人精品女人久 | 综合精品| 一区三区视频 | 日韩一区二区三区精品 | 国产99久久| 国产精品国产三级国产 | 久久成人国产精品 | 国产三区四区 | 成人免费在线观看 | 中文字幕国产日韩 | 亚洲成人高清 | 91成人免费视频 | 久久精品播放 | 免费观看黄色一级片 | 久久久久成人免费视频 | 国产高清在线视频 | 九九九视频 | 日韩在线播放视频 | 五月婷婷综合网 | 精品久久中文字幕97 | 亚洲一区中文字幕 | a级黄色免费看 | 国产尤物视频 | 天天av天天好逼 | 成人妇女免费播放久久久 | 看av网址| 成人av福利 | 午夜日韩| 久久精品视频一区二区三区 | 国产一区久久久 | 亚洲高清在线播放 | 在线观看免费黄色 | 久久福利国产 | 91香蕉视频在线观看免费 |