epoll實現簡單socket通訊

2021-10-07 13:51:26 字數 2732 閱讀 3295

epoll是常用的socket通訊方式,相比於select和poll來說,效率提公升了不止一點半點

其一:select中socket描述符(檔案描述符)集的資料結構為陣列,poll的檔案描述符集資料結構為鍊錶,無論陣列還是鍊錶,它們都是線性結構,當遍歷時,也只能線性遍歷;而epoll檔案描述符集採用的紅黑樹(平衡二叉樹的乙個變體)的資料結構,紅黑樹的遍歷則相比於線性遍歷,效率要高很多。

其二:select和poll對檔案描述符集先要拷貝到核心區,核心修改後再拷貝至使用者區,要經過2次拷貝;而epoll底層用的是共享記憶體的方式,即核心區與使用者區共享一片記憶體,無需拷貝,也就大大提高了效率。

#include // 建立一棵紅黑樹

int epoll_create(int size);

引數:

size: 沒意義, 隨便寫個數就行(早期epoll資料結構為hash表,需要指定表長,但後面改為紅黑樹後其實樹節點個數就沒有什麼意義了)

返回值;

>0: 檔案描述符, 操作epoll樹的根節點

epoll檢測的事件:

- epollin

- epolout

- epollerr

// 對epoll樹進行管理: 新增節點, 刪除節點, 修改已有的節點屬性

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

引數:- epfd: epoll_create的返回值, 通過這個值就可以找到紅黑樹

- op: 要進行什麼樣的操作

epoll_ctl_add: 註冊新節點, 新增到紅黑樹上

epoll_ctl_mod: 修改檢測的檔案描述符的屬性

epoll_ctl_del: 從紅黑樹上刪除節點

- fd: 要檢測的檔案描述符的值

- event: 檢測檔案描述符的什麼事件

// 檢測函式

struct epoll_event events[1000];

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

引數:- epfd: epoll_create的返回值(這棵紅黑樹的根節點), 通過這個值就可以找到紅黑樹

- events: 傳出引數, 儲存了發生變化的檔案描述符的資訊(陣列形式)

- maxevents: 第二個引數結構體陣列的大小

- timeout: 阻塞時間

- 0: 不阻塞

- -1: 一直阻塞, 知道檢測的fd有狀態變化, 解除阻塞

- >0: 阻塞的時長(毫秒)

返回值:

- 成功: 有多少個檔案描述符狀態發生了變化 > 0

- 失敗: -1

下面直接上**吧

server.c

#include #include #include #include #include #include #include int main()

// 2. 繫結 ip, port

struct sockaddr_in addr;

addr.sin_port = htons(1234);

addr.sin_family = af_inet;

addr.sin_addr.s_addr = inaddr_any;

int ret = bind(lfd, (struct sockaddr*)&addr, sizeof(addr));

if(ret == -1)

// 3. 監聽

ret = listen(lfd, 100);

if(ret == -1)

// 4. 建立epoll樹

int epfd = epoll_create(1000);//1000並沒有什麼意義

if(epfd == -1)

//5、將用於監聽的lfd掛的epoll樹上(紅黑樹)

struct epoll_event ev;//這個結構體記錄了檢測什麼檔案描述符的什麼事件

ev.events = epollin;

ev.data.fd = lfd;

epoll_ctl(epfd, epoll_ctl_add, lfd, &ev);//ev裡面記錄了檢測lfd的什麼事件

// 迴圈檢測 委託核心去處理

struct epoll_event events[1024];//當核心檢測到事件到來時會將事件寫到這個結構體陣列裡

while(1)

else

else}}

}}

close(lfd);

return 0;

}

client.c

#include #include #include #include #include #include int main()

printf("connect success!!!\n");

//讀取伺服器傳回的資料

char buffer[100];

//recv(sock, buffer, sizeof(buffer),0);

//printf("message form server: %s\n", buffer);

while(1)

//關閉套接字

close(sock);

return 0;

}

php簡單實現socket通訊

socket通訊的原理在這裡就不說了,它的用途還是比較廣泛的,我們可以使用 socket 來做乙個 api介面出來,也可以使用 socket 來實現兩個程式之間的通訊,我們來研究一下在 php開發 中如何實現socket通訊。由於socket服務端的 要監聽埠,等待接收請求,所以 php在做 soc...

Socket簡單實現ssh筆記

socket本質上就是在2臺網路互通的電腦之間,架設乙個通道,兩台電腦通過這個通道來實現資料的互相傳遞。我們知道網路 通訊 都 是基於 ip port 方能定位到目標的具體機器上的具體服務,作業系統有0 65535個埠,每個埠都可以獨立對外提供服務,如果 把乙個公司比做一台電腦 那公司的總機號碼就相...

Epoll 模型實現

while true else if m events i data.fd m listen sock fd 如果新監測到乙個socket使用者連線到了繫結的socket埠,建立新的連線。else if m events i events epollin 如果是已經連線的使用者,並且收到資料,那麼進...