多路IO轉接服務器 epoll

創建一個epoll句柄,參數size用來告訴內核監聽的文件描述符的個數,跟內存大小有關。

  #include <sys/epoll.h>

  int epoll_create(int size)   size:監聽數目? ? ?通過創建一個size大小的紅黑數來實現epoll句柄,返回epfd是該樹的根節點。

?

控制某個epoll監控的文件描述符上的事件:注冊、修改、刪除。

?

  #include <sys/epoll.h>

?

  int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

?

  epfd epoll_creat的句柄

?

  op 表示動作,用3個宏來表示:

?

    EPOLL_CTL_ADD?(注冊新的fdepfd)

?

    EPOLL_CTL_MOD?(修改已經注冊的fd的監聽事件)

?

    EPOLL_CTL_DEL?(epfd刪除一個fd)

?

  event 告訴內核需要監聽的事件,是一個地址

  struct epoll_event {

    __uint32_t events;      //EPOLLIN  EPOLLOUT  EPOLLERR

    epoll_data_t data;?

  };

  typedef union epoll_data {

    void *ptr;

    int fd;            //相當于函數中使用的fd

    uint32_t u32;

    uint64_t u64;

  } epoll_data_t;

?

等待所監控文件描述符上有事件的產生,類似于select()調用。

  #include <sys/epoll.h>

  int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)

  events 用來存內核得到事件的集合,是一個數組并且是傳出參數。

  maxevents 告之內核這個events有多大,這個maxevents的值不能大于創建epoll_create()時的size

  timeout 是超時時間

    -1 阻塞

    0 立即返回,非阻塞

    >0 指定毫秒

  返回值: 成功返回有多少文件描述符就緒,時間到時返回0,出錯返回-1

?

示例:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <ctype.h>#include "wrap.h"#define MAXLINE 8192
#define SERV_PORT 8000
#define OPEN_MAX 5000int main(int argc, char *argv[])
{int i, listenfd, connfd, sockfd;int  n, num = 0;ssize_t nready, efd, res;char buf[MAXLINE], str[INET_ADDRSTRLEN];socklen_t clilen;struct sockaddr_in cliaddr, servaddr;struct epoll_event tep, ep[OPEN_MAX];       //tep: epoll_ctl參數  ep[] : epoll_wait參數
listenfd = Socket(AF_INET, SOCK_STREAM, 0);int opt = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));      //端口復用
bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);Bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));Listen(listenfd, 20);efd = epoll_create(OPEN_MAX);               //創建epoll模型, efd指向紅黑樹根節點if (efd == -1)perr_exit("epoll_create error");tep.events = EPOLLIN; tep.data.fd = listenfd;           //指定lfd的監聽時間為"讀"res = epoll_ctl(efd, EPOLL_CTL_ADD, listenfd, &tep);    //將lfd及對應的結構體設置到樹上,efd可找到該樹if (res == -1)perr_exit("epoll_ctl error");for ( ; ; ) {/*epoll為server阻塞監聽事件, ep為struct epoll_event類型數組, OPEN_MAX為數組容量, -1表永久阻塞*/nready = epoll_wait(efd, ep, OPEN_MAX, -1); if (nready == -1)perr_exit("epoll_wait error");for (i = 0; i < nready; i++) {if (!(ep[i].events & EPOLLIN))      //如果不是"讀"事件, 繼續循環continue;if (ep[i].data.fd == listenfd) {    //判斷滿足事件的fd是不是lfd            clilen = sizeof(cliaddr);connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);    //接受鏈接
printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));printf("cfd %d---client %d\n", connfd, ++num);tep.events = EPOLLIN; tep.data.fd = connfd;res = epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &tep);if (res == -1)perr_exit("epoll_ctl error");} else {                                //不是lfd, sockfd = ep[i].data.fd;n = Read(sockfd, buf, MAXLINE);if (n == 0) {                       //讀到0,說明客戶端關閉鏈接res = epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL);  //將該文件描述符從紅黑樹摘除if (res == -1)perr_exit("epoll_ctl error");Close(sockfd);                  //關閉與該客戶端的鏈接printf("client[%d] closed connection\n", sockfd);} else if (n < 0) {                 //出錯perror("read n < 0 error: ");res = epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL);Close(sockfd);} else {                            //實際讀到了字節數for (i = 0; i < n; i++)buf[i] = toupper(buf[i]);   //轉大寫,寫回給客戶端
Write(STDOUT_FILENO, buf, n);Writen(sockfd, buf, n);}}}}Close(listenfd);Close(efd);return 0;
}

?

轉載于:https://www.cnblogs.com/lr1402585172/p/10754937.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384235.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384235.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384235.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux平臺上SQLite數據庫教程(二)——C語言API介紹

http://blog.csdn.net/u011192270/article/details/48086961 前言&#xff1a;本文將介紹幾個基本的SQLite3數據庫的C語言API接口&#xff0c;主要用到兩個文件&#xff1a;sqlite3.c、sqlite3.h。源碼地址&#xff1a;https://github.com/AnSwErYWJ/SQLite。 打開數據庫 1.原型…

epoll非阻塞IO

設置connfd套接字為非阻塞 flag fcntl(connfd, F_GETFL); flag | O_NONBLOCK; fcntl(connfd, F_SETFL, flag); 轉載于:https://www.cnblogs.com/lr1402585172/p/10758740.html

小白創建網站的曲折之路

小白創建網站的曲折之路 在虛擬機上創建網站 顧名思義&#xff0c;首先要有一個虛擬機。在網上百度一下后&#xff0c;我發現大家都在說使用一種叫做VMware Workstation的軟件進行虛擬機的構建 在這位好心人的幫助下我找到了Vmware Workstation的下載資源&#xff0c;并成功下…

Ubuntu 14.04數據庫服務器--mysql的安裝和配置

https://jingyan.baidu.com/article/425e69e6bbc6c7be14fc1640.html mysql是Oracle公司的一種開放源代碼的關系型數據庫管理系統&#xff0c;被廣泛應用于各中小網站&#xff0c;是一種跨平臺的數據庫管理系統&#xff0c;現在介紹一下如何在Ubuntu 14.04上安裝和配置mysql 工具…

javavbean

一、什么是javabeanJavaBean是一個遵循特定寫法的Java類&#xff0c;它通常具有如下特點&#xff1a;這個Java類必須具有一個無參的構造函數屬性必須私有化。私有化的屬性必須通過public類型的方法暴露給其它程序&#xff0c;并且方法的命名也必須遵守一定的命名規范。JavaBean…

Centos7下搭建LAMP環境,安裝wordpress(不會生產博客,只是一名博客搬運工)(菜鳥)

1.搭建MySQL數據庫 安裝MariaDB yum install mariadb-server -y 啟動MySQL服務 emctl start mariadb #啟動服務 emtcl enable marriadb#設置開機服務 設置MySQL賬戶和root密碼 mysqladmin -u root password ******* 2.安裝Apache服務 安裝Apache yum install httpd -y 啟動A…

(C語言版)棧和隊列(二)——實現順序存儲棧和順序存儲隊列的相關操作

http://blog.csdn.net/fisherwan/article/details/21479649 棧和隊列都有兩種實現方式&#xff0c;一種在之前已經寫過了&#xff0c;是鏈式存儲形式&#xff0c;另一種是順序存儲形式。也就是這里所寫的用數組的形式實現&#xff0c;和鏈式存儲形式相比&#xff0c;有幾個不同…

算法學習——貪心篇

貪心選擇是指應用同一規則&#xff0c;將原問題變為一個相似但是規模更小的問題&#xff0c;而后的每一步都是當前看起來最佳的選擇&#xff0c;且這種選擇只依賴于已做出的選擇&#xff0c;不依賴于未作出的選擇。 貪心算法說起來容易&#xff0c;操作起來卻經常有點玄學。&am…

使用基本MVC2模式創建新聞網站

轉載于:https://www.cnblogs.com/lr1402585172/p/10885084.html

棧(Stack),輕松解決數制轉換和括號匹配問題!

http://data.biancheng.net/view/9.html 棧&#xff0c;線性表的一種特殊的存儲結構。與學習過的線性表的不同之處在于棧只能從表的固定一端對數據進行插入和刪除操作&#xff0c;另一端是封死的。 圖1 棧結構示意圖由于棧只有一邊開口存取數據&#xff0c;稱開口的那一端為“…

第一章 TCP/IP協議族

一、協議族體系結構 TCP/IP協議族分為四層協議系統&#xff0c;自底向下分別為數據鏈路層、網絡層、傳輸層、應用層。 數據鏈路層常用ARP&#xff08;地址解析協議&#xff09;和RARP&#xff08;逆地址解析協議&#xff09;。在網絡層使用IP尋址&#xff0c;而在數據鏈路層使用…

二分(三分)+快速冪

之前學習的二分&#xff0c;現在感覺突然理解許多&#xff0c;補一下總結 首先&#xff0c;二分能夠解決什么樣的問題呢&#xff0c;個人認為&#xff0c;二分能夠快速解決已經知道答案范圍&#xff08;線性&#xff09;但是不知道確切答案的問題&#xff0c;例如在一個有序序列…

pthread_cleanup_push與pthread_cleanup_pop的目的 作用

http://blog.csdn.net/slj_win/article/details/7267483 首先你必須知道pthread_cleanup_push與pthread_cleanup_pop的目的(作用)是什么。 比如thread1: 執行 pthread_mutex_lock(&mutex); //一些會阻塞程序運行的調用&#xff0c;比如套接字的accept&#xff0c;等待客…

動態規劃淺談

接觸動態規劃這么久了&#xff0c;簡單談一下自己對動態規劃的理解。 動態規劃名字聽起來好像比比較高大上&#xff0c;可是事實上&#xff0c;人家就是比較高大上。&#xff08;抖個機靈&#xff09; 剛開始接觸動態規劃的時候覺得好可怕&#xff0c;這么復雜的問題我怎么能想…

Linux多線程——使用信號量同步線程

http://blog.csdn.net/ljianhui/article/details/10813469/ 信號量、同步這些名詞在進程間通信時就已經說過&#xff0c;在這里它們的意思是相同的&#xff0c;只不過是同步的對象不同而已。但是下面介紹的信號量的接口是用于線程的信號量&#xff0c;注意不要跟用于進程間通信…

linux下安裝erlang

1.安裝Erlang編譯依賴: yum -y install gcc glibc-devel make ncurses-devel openssl-devel xmlto perl wget 2.下載Erlang&#xff1a; wget http://www.erlang.org/download/otp_src_19.3.tar.gz 3.解壓并安裝 tar -xzvf otp_src_19.3.tar.gz cd otp_src_19.3 ./configure --…

Linux 線程同步的三種方法

http://blog.csdn.net/zsf8701/article/details/7844316 線程的最大特點是資源的共享性&#xff0c;但資源共享中的同步問題是多線程編程的難點。linux下提供了多種方式來處理線程同步&#xff0c;最常用的是互斥鎖、條件變量和信號量。 一、互斥鎖(mutex) 通過鎖機制實現線程…

Elixir特性

iex 退出&#xff1a;Ctrl-C 或Ctrl-G再輸入q 回車。 幫助文檔&#xff1a;h 查看輔函數列表 h IO 查看IO模塊幫助 h IO.puts 查看IO模塊中的puts函數的文檔 編譯和運行&#xff1a;創建一個hello.exs的文件。IO.puts "hello world"    //輸出hello world 使用el…

Elixir基礎

值類型 整數&#xff0c;包括十進制&#xff08;1234&#xff09;、十六進制&#xff08;0xcafe&#xff09;、八進制&#xff08;0o765&#xff09;和二進制&#xff08;0b1010&#xff09; 浮點數 原子&#xff0c;原子是常量&#xff0c;用于表現某些東西的名字&#xff0c;…

C++11新特性之八——函數對象function

http://www.cnblogs.com/yyxt/p/3987717.html 詳細請看《C Primer plus》(第六版中文版) http://www.cnblogs.com/lvpengms/archive/2011/02/21/1960078.html 備注&#xff1a; 函數對象&#xff1a; 盡管函數指針被廣泛用于實現函數回調&#xff0c;但C還提供了一個重要的實現…