国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端

這篇具有很好參考價(jià)值的文章主要介紹了【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

目錄

一,往期文章

二,基本概念

IO多路復(fù)用

select 模型

poll 模型

epoll 模型

select,poll,epoll 三者對(duì)比

三,函數(shù)清單

1.select 方法

2.fd_set 結(jié)構(gòu)體

3.poll 方法

4.struct pollfd 結(jié)構(gòu)體

5.epoll_create 方法

6.epoll_ctl 方法

7.epoll_wait 方法

8.struct epoll_event 結(jié)構(gòu)體

四,代碼實(shí)現(xiàn)

select 操作流程

select 完整代碼

poll 操作流程

poll 完整代碼

epoll 操作流程

epoll 完整代碼


一,往期文章

【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】1.Linux下實(shí)現(xiàn)單客戶連接的tcp服務(wù)端

【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】2.引入多線程實(shí)現(xiàn)多客戶端連接的tcp服務(wù)端

二,基本概念

IO多路復(fù)用

介紹

  • I/O多路復(fù)用(IO Multiplexing)是一種并發(fā)編程技術(shù),用于同時(shí)監(jiān)視多個(gè)I/O事件并選擇就緒的事件進(jìn)行處理。它可以通過一個(gè)線程或進(jìn)程同時(shí)處理多個(gè)I/O操作,而不需要為每個(gè)I/O操作創(chuàng)建一個(gè)獨(dú)立的線程或進(jìn)程。I/O多路復(fù)用可以提高系統(tǒng)的并發(fā)性能,減少資源的消耗。
  • 在傳統(tǒng)的編程模型中,每個(gè)I/O操作通常都需要一個(gè)獨(dú)立的線程或進(jìn)程來處理。這種方式在面對(duì)大量的并發(fā)連接時(shí),會(huì)導(dǎo)致系統(tǒng)資源的浪費(fèi)和性能下降。而I/O多路復(fù)用通過使用一種事件驅(qū)動(dòng)的方式,可以同時(shí)監(jiān)視多個(gè)I/O事件,只有當(dāng)有事件就緒時(shí)才進(jìn)行相應(yīng)的處理,從而提高了系統(tǒng)的并發(fā)性能。
  • 常見的I/O多路復(fù)用函數(shù)包括"select"、"poll"、"epoll"等。這些函數(shù)可以同時(shí)監(jiān)視多個(gè)文件描述符的狀態(tài),并確定哪些文件描述符已經(jīng)準(zhǔn)備好可進(jìn)行相應(yīng)的讀取、寫入或異常處理。通過使用這些函數(shù),可以避免為每個(gè)I/O操作創(chuàng)建一個(gè)獨(dú)立的線程或進(jìn)程,從而減少了系統(tǒng)資源的消耗。
  • I/O多路復(fù)用的工作原理是通過一個(gè)事件循環(huán)來監(jiān)視多個(gè)I/O事件。當(dāng)有一個(gè)或多個(gè)事件就緒時(shí),事件循環(huán)會(huì)通知程序進(jìn)行相應(yīng)的處理。這種方式可以大大提高系統(tǒng)的并發(fā)性能,減少了線程或進(jìn)程的切換開銷。

總結(jié)文章來源地址http://www.zghlxwxcb.cn/news/detail-627390.html

  • I/O多路復(fù)用是一種并發(fā)編程技術(shù),用于同時(shí)監(jiān)視多個(gè)I/O事件并選擇就緒的事件進(jìn)行處理。它可以提高系統(tǒng)的并發(fā)性能,減少資源的消耗。通過使用I/O多路復(fù)用函數(shù),可以避免為每個(gè)I/O操作創(chuàng)建一個(gè)獨(dú)立的線程或進(jìn)程,從而提高系統(tǒng)的效率。

select 模型

前言

  • io多路復(fù)用select模型是一種用于實(shí)現(xiàn)高效的事件驅(qū)動(dòng)I/O的技術(shù)。它的基本思想是在一個(gè)線程中同時(shí)監(jiān)視多個(gè)文件描述符(包括套接字、管道等),并在有事件到達(dá)時(shí)進(jìn)行處理。
  • 在傳統(tǒng)的阻塞式I/O中,一個(gè)線程只能處理一個(gè)請(qǐng)求,并且需要等待I/O操作完成后才能處理下一個(gè)請(qǐng)求。而在使用select模型時(shí),它可以同時(shí)監(jiān)視多個(gè)文件描述符的狀態(tài),當(dāng)有一個(gè)或多個(gè)文件描述符準(zhǔn)備好進(jìn)行讀寫時(shí),就可以通過select函數(shù)得知,并進(jìn)行相應(yīng)的處理操作。
  • 通過使用select模型,可以在一個(gè)線程中同時(shí)處理多個(gè)文件描述符的I/O操作,從而提高程序的并發(fā)性和響應(yīng)性能。它適用于需要同時(shí)處理多個(gè)客戶端請(qǐng)求的情況,比如服務(wù)器程序中的多連接處理、多用戶聊天程序等。在實(shí)際應(yīng)用中,select模型已被廣泛使用,并且也衍生出其他更高效的模型,如poll、epoll、kqueue等。

定義

  • "select函數(shù)"是一種用于在一組文件描述符(文件、套接字、管道等)中選擇就緒的文件描述符的函數(shù)。它在不同的操作系統(tǒng)中有不同的實(shí)現(xiàn)。

功能

  • "select函數(shù)"的主要功能是監(jiān)視文件描述符的狀態(tài)并確定哪些文件描述符已經(jīng)準(zhǔn)備好可進(jìn)行相應(yīng)的讀取、寫入或異常處理。

工作原理

  • 當(dāng)調(diào)用"select函數(shù)"時(shí),在指定的文件描述符集合上進(jìn)行監(jiān)視。當(dāng)有一個(gè)或多個(gè)文件描述符準(zhǔn)備好進(jìn)行讀取、寫入或出現(xiàn)異常時(shí),"select函數(shù)"將返回,告訴程序哪些文件描述符已經(jīng)就緒。程序可以利用這些就緒的文件描述符進(jìn)行相應(yīng)的I/O操作。

優(yōu)點(diǎn)

  • 多路復(fù)用:"select函數(shù)"可以同時(shí)監(jiān)視多個(gè)文件描述符的狀態(tài),這些文件描述符可以是與網(wǎng)絡(luò)連接相關(guān)的套接字、標(biāo)準(zhǔn)輸入/輸出等。通過使用"select函數(shù)",可以避免單獨(dú)為每個(gè)文件描述符創(chuàng)建線程或進(jìn)程來處理事件,從而實(shí)現(xiàn)更高效的并發(fā)編程。
  • 非阻塞:使用"select函數(shù)"可以將文件描述符設(shè)置為非阻塞模式,因此在等待事件就緒的同時(shí),可以執(zhí)行其他任務(wù),充分利用CPU資源。
  • 兼容性:"select函數(shù)"是一種跨平臺(tái)的解決方案,在大多數(shù)操作系統(tǒng)上都得到支持。

缺點(diǎn)

  • 所有文件描述符集合的線性遍歷:在調(diào)用"select函數(shù)"時(shí),需要將待監(jiān)視的文件描述符集合傳遞給函數(shù)。然而,在文件描述符數(shù)量較大時(shí),需要線性遍歷集合以找到就緒的文件描述符,這可能導(dǎo)致性能下降。
  • 限制文件描述符數(shù)量:不同操作系統(tǒng)對(duì)最大支持的文件描述符數(shù)量有限制,如果需要監(jiān)視的文件描述符數(shù)量超出此限制,"select函數(shù)"可能無法滿足需求。此外,當(dāng)文件描述符數(shù)量增加時(shí),調(diào)用"select函數(shù)"的開銷也會(huì)增加。

總結(jié)

  • "select函數(shù)"是一種常用的函數(shù),用于實(shí)現(xiàn)多路復(fù)用I/O操作,監(jiān)視多個(gè)文件描述符的狀態(tài),并確定哪些文件描述符已準(zhǔn)備好進(jìn)行相應(yīng)的I/O操作。
  • 它在網(wǎng)絡(luò)編程中特別有用,可以實(shí)現(xiàn)高效的事件驅(qū)動(dòng)編程。

poll 模型

前言

  • "poll函數(shù)"提供了一種替代"select函數(shù)"的方法,用于監(jiān)視一組文件描述符的狀態(tài)。

定義

  • "poll函數(shù)"是一個(gè)系統(tǒng)調(diào)用,用于監(jiān)視一組文件描述符的狀態(tài)并確定哪些文件描述符已經(jīng)準(zhǔn)備好可進(jìn)行相應(yīng)的讀取、寫入或異常處理。

功能

  • "poll函數(shù)"的主要功能是監(jiān)視文件描述符的狀態(tài),類似于"select函數(shù)"。它可以同時(shí)監(jiān)視多個(gè)文件描述符,以確定它們是否處于可讀、可寫或異常狀態(tài)。

工作原理

  • 當(dāng)調(diào)用"poll函數(shù)"時(shí),它會(huì)監(jiān)視指定的文件描述符并等待事件的發(fā)生。如果有一個(gè)或多個(gè)文件描述符準(zhǔn)備好進(jìn)行讀取、寫入或出現(xiàn)異常,"poll函數(shù)"將返回,并標(biāo)記就緒的文件描述符的狀態(tài)。程序可以根據(jù)文件描述符的狀態(tài)進(jìn)行相應(yīng)的I/O操作。

優(yōu)點(diǎn)

  • "poll函數(shù)"解決了"select函數(shù)"中線性遍歷文件描述符集合的性能問題,它使用輪詢算法,避免了遍歷集合的開銷。
  • "poll函數(shù)"支持監(jiān)視大量文件描述符,沒有文件描述符數(shù)量的限制。
  • "poll函數(shù)"比"select函數(shù)"更加可讀,并且在處理異常情況時(shí)更加靈活。

缺點(diǎn)

  • "poll函數(shù)"的可移植性可能略低于"select函數(shù)",因?yàn)椴煌牟僮飨到y(tǒng)和編程語言對(duì)"poll函數(shù)"的實(shí)現(xiàn)可能有所不同。
  • 當(dāng)處理大量文件描述符時(shí),"poll函數(shù)"的性能可能會(huì)受到影響。

總結(jié)

  • "poll函數(shù)"是一種常用的函數(shù),用于實(shí)現(xiàn)多路復(fù)用I/O操作,它可以同時(shí)監(jiān)視多個(gè)文件描述符的狀態(tài)并確定哪些文件描述符已準(zhǔn)備好進(jìn)行相應(yīng)的I/O操作。
  • 相對(duì)于"select函數(shù)","poll函數(shù)"提供了更好的性能和可讀性。但仍需要考慮平臺(tái)兼容性和大量文件描述符的性能問題。

epoll 模型

前言

  • epoll(事件輪詢)是Linux操作系統(tǒng)提供的一種高性能I/O多路復(fù)用機(jī)制,在處理大規(guī)模的并發(fā)連接時(shí)具有優(yōu)越的效率和可擴(kuò)展性。它通過使用內(nèi)核的事件通知機(jī)制來同時(shí)監(jiān)視和處理多個(gè)文件描述符的事件,大大減少了輪詢的開銷,提高了系統(tǒng)的并發(fā)性能。
  • 與傳統(tǒng)的select和poll函數(shù)相比,epoll在處理大規(guī)模并發(fā)連接時(shí)具有更高的效率。

基本流程

  1. 調(diào)用epoll_create函數(shù)創(chuàng)建一個(gè)epoll實(shí)例,并獲得一個(gè)文件描述符(epfd)。
  2. 使用epoll_ctl函數(shù)向epoll實(shí)例中加入需要監(jiān)視的文件描述符和對(duì)應(yīng)的事件類型,包括讀、寫、錯(cuò)誤等。
  3. 使用epoll_wait函數(shù)阻塞等待事件的發(fā)生,當(dāng)有文件描述符就緒時(shí),epoll_wait將返回就緒的文件描述符集合。
  4. 遍歷就緒的文件描述符集合,進(jìn)行相應(yīng)的I/O操作。

工作原理

  1. 調(diào)用epoll_create函數(shù)創(chuàng)建一個(gè)epoll實(shí)例,獲得一個(gè)epoll文件描述符(epfd)。
  2. 使用epoll_ctl函數(shù)向epoll實(shí)例注冊(cè)需要監(jiān)視的文件描述符和相應(yīng)的事件類型,并將其加入到內(nèi)核維護(hù)的事件表中。
  3. 調(diào)用epoll_wait函數(shù)阻塞等待事件的發(fā)生,此時(shí)線程會(huì)進(jìn)入休眠狀態(tài),不再需要輪詢文件描述符。
  4. 當(dāng)被監(jiān)視的文件描述符上的事件發(fā)生時(shí),內(nèi)核會(huì)將事件加入到就緒列表中,同時(shí)喚醒處于阻塞狀態(tài)的線程。
  5. epoll_wait函數(shù)返回時(shí),通過遍歷就緒列表,獲取到就緒的文件描述符集合。
  6. 應(yīng)用程序根據(jù)文件描述符的就緒事件類型進(jìn)行相應(yīng)的I/O操作,如讀取、寫入數(shù)據(jù)等。

相關(guān)函數(shù)

  • epoll_create(int size):創(chuàng)建一個(gè)epoll實(shí)例。
  • epoll_ctl(int epfd, int op, int fd, struct epoll_event* event):向epoll實(shí)例注冊(cè)/修改/刪除一個(gè)文件描述符及其對(duì)應(yīng)的事件。
  • epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout):等待事件的發(fā)生,并獲取就緒的文件描述符。

事件類型(events參數(shù))

  • EPOLLIN:文件描述符上有數(shù)據(jù)可讀。
  • EPOLLOUT:文件描述符上可以寫入數(shù)據(jù)。
  • EPOLLERR:文件描述符發(fā)生錯(cuò)誤。
  • EPOLLHUP:文件描述符掛起。
  • EPOLLET:邊緣觸發(fā)模式。
  • EPOLLONESHOT:一次性事件,事件發(fā)生后會(huì)被自動(dòng)從epoll實(shí)例中刪除。

優(yōu)點(diǎn)

  1. 高性能:epoll使用紅黑樹(內(nèi)核使用的數(shù)據(jù)結(jié)構(gòu)),就緒列表和事件通知機(jī)制,避免了遍歷整個(gè)文件描述符集合的開銷,在大規(guī)模并發(fā)連接時(shí)性能比傳統(tǒng)的select和poll函數(shù)更好。
  2. 可擴(kuò)展性:epoll的設(shè)計(jì)支持超大規(guī)模的并發(fā)連接,能夠更好地適應(yīng)高并發(fā)的網(wǎng)絡(luò)環(huán)境。
  3. 邊緣觸發(fā)模式:epoll提供了邊緣觸發(fā)(ET)模式,只有在文件描述符狀態(tài)發(fā)生變化時(shí)才觸發(fā)事件通知,相比于水平觸發(fā)(LT)模式可以減少事件通知次數(shù),提高效率。
  4. 持久化的事件注冊(cè):注冊(cè)事件時(shí),可以選擇EPOLLONESHOT標(biāo)志,使得內(nèi)核在將事件通知給應(yīng)用程序后,自動(dòng)將該事件從epoll實(shí)例中刪除,避免重復(fù)通知。
  5. 支持多種數(shù)據(jù)結(jié)構(gòu):epoll支持紅黑樹和鏈表兩種數(shù)據(jù)結(jié)構(gòu),用于快速查找文件描述符和就緒列表的操作,提高了處理效率。
  6. 大規(guī)模并發(fā):epoll可以高效地管理大量的文件描述符,支持高并發(fā)的網(wǎng)絡(luò)編程。

總結(jié)

  • epoll是Linux操作系統(tǒng)提供的一種高性能I/O多路復(fù)用機(jī)制,它通過內(nèi)核的事件通知和就緒列表,能同時(shí)監(jiān)視和處理大量的文件描述符。它具有高性能、可擴(kuò)展性和邊緣觸發(fā)模式等特點(diǎn),是開發(fā)高并發(fā)網(wǎng)絡(luò)應(yīng)用的重要工具。

select,poll,epoll 三者對(duì)比

共同點(diǎn)

  • select,?poll, 和?epoll?都是在事件驅(qū)動(dòng)的網(wǎng)絡(luò)編程中用于多路復(fù)用 I/O 的機(jī)制。它們的主要目標(biāo)是在一個(gè)線程內(nèi)同時(shí)處理多個(gè)文件描述符的 I/O 操作,而不是為每個(gè)文件描述符創(chuàng)建一個(gè)單獨(dú)的線程或進(jìn)程。

優(yōu)缺點(diǎn)分析

  • select
    • 優(yōu)點(diǎn)
      • 廣泛支持,可以在大部分的操作系統(tǒng)上使用。
      • 可以處理多種類型的文件描述符(包括普通文件、套接字文件等)。
    • 缺點(diǎn)
      • 效率較低,因?yàn)樵谡{(diào)用?select?時(shí)需要遍歷整個(gè)文件描述符集合,無論是否有真正的 I/O 事件發(fā)生。
      • 最大文件描述符數(shù)量有限,默認(rèn)情況下通常為 1024 個(gè)。
      • select?函數(shù)在每次調(diào)用時(shí)都需要修改傳入的文件描述符集合,導(dǎo)致效率低下。
  • poll
    • 優(yōu)點(diǎn)
      • 不受最大文件描述符數(shù)量限制,可以動(dòng)態(tài)地管理文件描述符的數(shù)量。
      • 效率較高,因?yàn)闊o需遍歷整個(gè)文件描述符集合,只處理有事件發(fā)生的文件描述符。
    • 缺點(diǎn)
      • 與?select?類似,需要遍歷整個(gè)文件描述符集合來查找是否有事件發(fā)生。
      • 對(duì)于大量的文件描述符,性能可能下降。
  • epoll
    • 優(yōu)點(diǎn)
      • 高效的事件通知機(jī)制,能夠快速響應(yīng)大量的并發(fā)連接。
      • 沒有最大文件描述符數(shù)量限制。
      • 使用回調(diào)機(jī)制,只處理活躍的文件描述符,避免無效的遍歷。
      • 支持水平觸發(fā)和邊緣觸發(fā)兩種工作模式。
    • 缺點(diǎn)
      • 只在 Linux 系統(tǒng)上可用,不具有跨平臺(tái)性。
      • API 相對(duì)復(fù)雜,有一定的學(xué)習(xí)成本。

總結(jié)

  • epoll?在性能和擴(kuò)展性方面優(yōu)于?select?和?poll。它在支持大規(guī)模并發(fā)連接和高效的事件通知方面表現(xiàn)出色。但如果只需要處理數(shù)百個(gè)并發(fā)連接,并且需要在多個(gè)平臺(tái)上運(yùn)行,select?或?poll?也可以是合理的選擇。

三,函數(shù)清單

1.select 方法

#include <sys/select.h>

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

功能

  • 監(jiān)視文件描述符的狀態(tài)并確定哪些文件描述符已經(jīng)準(zhǔn)備好可進(jìn)行相應(yīng)的讀取、寫入或異常處理。

參數(shù)

  • nfds:監(jiān)視文件描述符集合的最大值加1。
  • readfds:要監(jiān)視可讀事件的文件描述符集合。
  • writefds:要監(jiān)視可寫事件的文件描述符集合。
  • exceptfds:要監(jiān)視異常事件的文件描述符集合。
  • timeout:超時(shí)時(shí)間,可以設(shè)置為NULL(無限等待),或者指定一個(gè)時(shí)間段。

返回值

  • 修改給定的文件描述符集合,并返回就緒的文件描述符的數(shù)量,若超時(shí)則返回0,若出錯(cuò)則返回-1。

2.fd_set 結(jié)構(gòu)體

typedef struct {
    unsigned long fds_bits[FD_SETSIZE / (8 * sizeof(unsigned long))];
} fd_set;

功能

  • fd_set?是一個(gè)用于存儲(chǔ)文件描述符集合的數(shù)據(jù)結(jié)構(gòu)。它通常是一個(gè)位圖,每個(gè)位表示一個(gè)文件描述符的狀態(tài)。在使用?select?函數(shù)時(shí),通常需要使用?fd_set?結(jié)構(gòu)體來設(shè)置、檢查和處理文件描述符集合。

成員

  • fds_bits:用于存儲(chǔ)文件描述符信息的數(shù)組。FD_SETSIZE?宏定義了數(shù)組的大?。J(rèn)為1024),表明文件描述符集合的最大容量。

fd_set?結(jié)構(gòu)體用于存儲(chǔ)文件描述符的集合,并通過相應(yīng)的宏來進(jìn)行相關(guān)操作,如添加、刪除和檢查文件描述符。

  • FD_ZERO(fd_set *set):清空?fd_set?結(jié)構(gòu)體,將其初始化為空集。
  • FD_SET(int fd, fd_set *set):將指定的文件描述符?fd?添加到?fd_set?結(jié)構(gòu)體中。
  • FD_CLR(int fd, fd_set *set):從?fd_set?結(jié)構(gòu)體中移除指定的文件描述符?fd。
  • FD_ISSET(int fd, fd_set *set):檢查指定的文件描述符?fd?是否在?fd_set?結(jié)構(gòu)體中。如果存在于集合中,則返回非零值,否則返回零。
  • FD_COPY(fd_set *src_set, fd_set *dest_set):將?src_set?結(jié)構(gòu)體中的文件描述符復(fù)制到?dest_set?結(jié)構(gòu)體中。
  • FD_SETSIZE:表示在一個(gè)?fd_set?結(jié)構(gòu)體中可容納的最大文件描述符數(shù)量。默認(rèn)情況下,在大多數(shù)系統(tǒng)上都設(shè)置為 1024??梢允褂眠@個(gè)宏來確定在使用?select?函數(shù)時(shí)?fd_set?結(jié)構(gòu)體的大小。

注意事項(xiàng)

  • 需要注意的是,fd_set?結(jié)構(gòu)體在使用?select?函數(shù)時(shí)會(huì)被修改,因此在每次調(diào)用?select?之前需要重新設(shè)置需要監(jiān)聽的文件描述符。

3.poll 方法

#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

功能

  • 監(jiān)視文件描述符的狀態(tài)并確定哪些文件描述符已經(jīng)準(zhǔn)備好可進(jìn)行相應(yīng)的讀取、寫入或異常處理。

參數(shù)

  • fds:指向一個(gè)結(jié)構(gòu)體數(shù)組的指針,每個(gè)結(jié)構(gòu)體中包含待監(jiān)視的文件描述符和監(jiān)視事件類型。
  • nfds:結(jié)構(gòu)體數(shù)組的大小,即待監(jiān)視的文件描述符的最大值加1。
  • timeout:指定一個(gè)超時(shí)值,以毫秒為單位,控制?poll?的阻塞行為,可以設(shè)置為以下幾種情況之一:
    • timeout?大于0,表示阻塞?timeout?毫秒后超時(shí)返回。
    • timeout?等于0,表示立即返回,不進(jìn)行阻塞。
    • timeout?小于0,表示無限阻塞,直到有事件發(fā)生。

返回值

  • 修改給定的結(jié)構(gòu)體數(shù)組,并返回就緒的文件描述符數(shù)量,若超時(shí)則返回0,若出錯(cuò)則返回-1。

4.struct pollfd 結(jié)構(gòu)體

struct pollfd {
    int fd;         // 關(guān)注的文件描述符
    short events;   // 等待的事件類型
    short revents;  // 實(shí)際發(fā)生的事件類型
};

功能

  • poll函數(shù)通過?struct pollfd?結(jié)構(gòu)體來描述文件描述符和關(guān)注的事件類型。

成員

  • fd:表示文件描述符。
  • events:表示關(guān)注的事件類型,可以是以下幾種事件之一或它們的結(jié)合:
    • POLLIN:可讀事件。
    • POLLOUT:可寫事件。
    • POLLERR:錯(cuò)誤事件。
    • POLLHUP:掛起事件。
  • revents:在?poll?返回時(shí),revents?字段表示實(shí)際發(fā)生的事件類型,由操作系統(tǒng)填充。

5.epoll_create 方法

#include <sys/epoll.h>

int epoll_create(int size);

功能

  • 創(chuàng)建一個(gè)epoll實(shí)例,并返回一個(gè)文件描述符用于操作該實(shí)例。(會(huì)在內(nèi)核中分配并初始化一個(gè)用于存儲(chǔ)事件的鏈表數(shù)據(jù)結(jié)構(gòu))

參數(shù)

  • size:表示實(shí)例能夠監(jiān)視的文件描述符的最大數(shù)量(在Linux 2.6.8之后被忽略)。

返回值

  • 如果成功,這些系統(tǒng)調(diào)用返回一個(gè)文件描述符(一個(gè)非負(fù)整數(shù))。如果出現(xiàn)錯(cuò)誤,則返回-1,并設(shè)置errno來指示錯(cuò)誤。

6.epoll_ctl 方法

#include <sys/epoll.h>

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

功能

  • 向epoll實(shí)例添加/修改/刪除一個(gè)文件描述符及其對(duì)應(yīng)的事件。

參數(shù)

  • epfd:為epoll實(shí)例的文件描述符。
  • op:指定操作類型,可以是EPOLL_CTL_ADD(添加)、EPOLL_CTL_MOD(修改)或EPOLL_CTL_DEL(刪除)。
  • fd:待操作的文件描述符。
  • event:指向一個(gè)epoll_event結(jié)構(gòu)體,描述了待添加/修改/刪除的事件類型。

返回值

  • 當(dāng)成功時(shí),epoll_ctl()返回零。當(dāng)發(fā)生錯(cuò)誤時(shí),epoll_ctl()返回-1,并設(shè)置errno來指示錯(cuò)誤。

7.epoll_wait 方法

#include <sys/epoll.h>

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

功能

  • 等待事件的發(fā)生并獲取就緒的文件描述符。

參數(shù)

  • epfd:epoll實(shí)例的文件描述符。
  • events:存儲(chǔ)就緒事件的數(shù)組。
  • maxevents:表示events數(shù)組的最大大小。
  • timeout:指定超時(shí)時(shí)間(以毫秒為單位),可以設(shè)置為-1(無限等待)或0(立即返回)。

返回值

  • 若成功則返回就緒的文件描述符的數(shù)量,若超時(shí)則返回0,若出錯(cuò)則返回-1,并設(shè)置errno來指示錯(cuò)誤。

8.struct epoll_event 結(jié)構(gòu)體

typedef union epoll_data {
    void    *ptr;
    int      fd;
    uint32_t u32;
    uint64_t u64;
} epoll_data_t;

struct epoll_event {
    uint32_t     events;    /* Epoll events */
    epoll_data_t data;      /* User data variable */
};

功能

  • 描述一個(gè)文件描述符及其對(duì)應(yīng)的事件類型。

成員

  • events:表示關(guān)注的事件類型,包括EPOLLIN(可讀)、EPOLLOUT(可寫)、EPOLLERR(錯(cuò)誤)、EPOLLHUP(掛起)等。
  • data:可以是一個(gè)32或64位的整數(shù),或者一個(gè)指向void的指針,用于存儲(chǔ)與文件描述符關(guān)聯(lián)的用戶數(shù)據(jù)。

四,代碼實(shí)現(xiàn)

select 操作流程

  1. 創(chuàng)建并初始化fd_set集合:fd_set是一個(gè)用于存儲(chǔ)文件描述符的數(shù)據(jù)結(jié)構(gòu)。通過定義一個(gè)fd_set變量,并使用FD_ZERO和FD_SET宏來初始化。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  2. 設(shè)置超時(shí)時(shí)間:通過設(shè)置timeval結(jié)構(gòu)體來指定select函數(shù)的超時(shí)時(shí)間。如果不需要設(shè)置超時(shí)時(shí)間,可以將該參數(shù)設(shè)置為NULL。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  3. 調(diào)用select函數(shù):使用select函數(shù)來等待文件描述符的就緒事件。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  4. 檢查select函數(shù)的返回值:根據(jù)select函數(shù)的返回值,確定是否有文件描述符就緒。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  5. 遍歷就緒文件描述符集合:通過遍歷fd_set集合來判斷哪些文件描述符已經(jīng)就緒。使用FD_ISSET宏來判斷文件描述符是否在集合中。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)

注意事項(xiàng)

  • 在使用select函數(shù)之前,需要手動(dòng)設(shè)置文件描述符的阻塞或非阻塞狀態(tài)。
  • 每次調(diào)用select函數(shù)之后,需要重新初始化fd_set集合,并將需要監(jiān)聽的文件描述符重新設(shè)置進(jìn)去。
  • select函數(shù)每次只能監(jiān)聽一部分文件描述符,因此在大規(guī)模并發(fā)連接時(shí),性能可能會(huì)受到限制。
  • select函數(shù)支持的文件描述符數(shù)量有限,通常取決于操作系統(tǒng)的限制。

總結(jié)

  • 通過創(chuàng)建并初始化fd_set集合(準(zhǔn)備需要監(jiān)聽的文件描述符集合),設(shè)置超時(shí)時(shí)間,并使用select函數(shù)進(jìn)行監(jiān)聽文件描述符的就緒事件。然后根據(jù)select函數(shù)的返回值和遍歷就緒文件描述符集合來執(zhí)行相應(yīng)的I/O操作。

select 完整代碼

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/select.h>


#define BUFFER_LENGTH   1024

int init_server(int port){
    //獲取服務(wù)端fd,通常為3,前面0,1,2用于表示標(biāo)準(zhǔn)輸入,輸出,錯(cuò)誤值
    int sfd = socket(AF_INET,SOCK_STREAM,0);

    if(-1 == sfd){
        printf("socket error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    struct sockaddr_in servAddr;
    memset(&servAddr,0,sizeof(struct sockaddr_in));
    servAddr.sin_family = AF_INET;  //ipv4
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);   //0.0.0.0
    servAddr.sin_port = htons(port);
    
    //綁定IP和端口號(hào)
    if(-1 == bind(sfd,(struct sockaddr*)&servAddr,sizeof(struct sockaddr_in)))
    {
        printf("bind error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    //監(jiān)聽該套接字上的連接
    if(-1 == listen(sfd,10))
    {
        printf("listen error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    return sfd;
}

int main(int argc,char *argv[]){

    if(argc < 2)return -1;

    int port = atoi(argv[1]);       //字符串轉(zhuǎn)整型
    int sfd = init_server(port);
    printf("server fd: %d\n",sfd);
    if(sfd == -1)return -1;

    fd_set rfds,rset;    //fd位數(shù)組
    FD_ZERO(&rfds);
    FD_SET(sfd,&rfds);

    int maxfd = sfd;
    int cfd = 0;
    struct sockaddr_in clientAddr;
    socklen_t len = sizeof(struct sockaddr_in);
    
    while (1)   //表示每周都去東莞      主線程
    {
        rset = rfds;
        int nready = select(maxfd+1,&rset,NULL,NULL,NULL);    //系統(tǒng)調(diào)用

        if(FD_ISSET(sfd,&rset)){
            cfd = accept(sfd,(struct sockaddr*)&clientAddr,&len);   //阻塞等待客戶端連接
            printf("client fd: %d\n",cfd);
            FD_SET(cfd,&rfds);
            if(cfd > maxfd)maxfd = cfd;     //將需要監(jiān)聽的文件描述符重新設(shè)置進(jìn)去

            if(--nready == 0)continue;      //超時(shí)時(shí)間到,沒有就緒的文件描述符
            
        }

        int i = 0;
        //服務(wù)端sfd=3
        for(i = sfd+1;i<=maxfd;i++){
            if(FD_ISSET(i,&rset)){
                //有bug,下一個(gè)客戶端發(fā)送數(shù)據(jù)后,上一個(gè)客戶端發(fā)送數(shù)據(jù)不能接收
                char data[BUFFER_LENGTH] = {0};
                int recvLen = recv(cfd,data,BUFFER_LENGTH,0);
                if(recvLen == 0){
                    printf("cfd: %d disconnect\n",cfd);
                    close(cfd);
                    break;  //客戶端斷開連接
                }
                printf("recv cfd: %d data: %s\n",cfd,data);

                send(cfd,data,recvLen,0);
            }
        }
    }
    
    return 0;
}

poll 操作流程

  1. 準(zhǔn)備需要監(jiān)聽的文件描述符集合。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  2. 設(shè)置超時(shí)時(shí)間(可選)。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  3. 調(diào)用?poll?函數(shù)等待就緒事件。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  4. 檢查?poll?函數(shù)的返回值。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)

注意事項(xiàng)

  • 在使用?poll?函數(shù)之前,需要設(shè)置文件描述符的阻塞或非阻塞狀態(tài)。
  • 每次調(diào)用?poll?函數(shù)之前,需要重新設(shè)置需要監(jiān)聽的文件描述符集合。
  • poll?函數(shù)一次可以監(jiān)聽多個(gè)文件描述符,相比于?select?函數(shù)能更好地適應(yīng)高并發(fā)環(huán)境。
  • poll?函數(shù)將就緒的文件描述符信息填充到?revents?字段中,可以通過按位與操作來判斷文件描述符的就緒事件類型。

總結(jié)

  • 通過準(zhǔn)備需要監(jiān)聽的文件描述符集合,調(diào)用?poll?函數(shù)等待就緒事件,然后根據(jù)返回值和遍歷就緒文件描述符集合來執(zhí)行相應(yīng)的 I/O 操作。

poll 完整代碼

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <poll.h>


#define BUFFER_LENGTH   1024
#define POLL_LENGTH   1024

int init_server(int port){
    //獲取服務(wù)端fd,通常為3,前面0,1,2用于指定輸入,輸出,錯(cuò)誤值
    int sfd = socket(AF_INET,SOCK_STREAM,0);

    if(-1 == sfd){
        printf("socket error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    struct sockaddr_in servAddr;
    memset(&servAddr,0,sizeof(struct sockaddr_in));
    servAddr.sin_family = AF_INET;  //ipv4
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);   //0.0.0.0
    servAddr.sin_port = htons(port);
    
    //綁定IP和端口號(hào)
    if(-1 == bind(sfd,(struct sockaddr*)&servAddr,sizeof(struct sockaddr_in)))
    {
        printf("bind error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    //監(jiān)聽該套接字上的連接
    if(-1 == listen(sfd,10))
    {
        printf("listen error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    return sfd;
}

int main(int argc,char *argv[]){

    if(argc < 2)return -1;

    int port = atoi(argv[1]);
    int sfd = init_server(port);
    printf("server fd: %d\n",sfd);
    if(sfd == -1)return -1;

    struct pollfd fds[POLL_LENGTH] = {0};   // 定義一個(gè) pollfd 數(shù)組,大小根據(jù)需要監(jiān)聽的文件描述符個(gè)數(shù)來設(shè)置
    fds[sfd].fd = sfd;  // 設(shè)置第一個(gè)需要監(jiān)聽的文件描述符
    fds[sfd].events = POLLIN;   // 設(shè)置需要監(jiān)聽的事件類型
    fds[sfd].revents = 0; // 清空返回的就緒事件

    int maxfd = sfd;
    int cfd;
    struct sockaddr_in clientAddr;
    socklen_t len = sizeof(struct sockaddr_in);
    while (1)
    {
        int nready = poll(fds,maxfd+1,-1);
        if(fds[sfd].revents & POLLIN){
            cfd = accept(sfd,(struct sockaddr*)&clientAddr,&len);   //阻塞等待客戶端連接
            printf("client fd: %d\n",cfd);

            fds[cfd].fd = cfd;
            fds[cfd].events = POLLIN;

            if(cfd > maxfd)maxfd = cfd;

            if(--nready == 0)continue;
        }

        int i = 0;
        for(i=0;i<=maxfd;i++){
            if(fds[i].revents & POLLIN){
                char data[BUFFER_LENGTH] = {0};
                int recvLen = recv(cfd,data,BUFFER_LENGTH,0);
                if(recvLen == 0){
                    //有點(diǎn)問題
                    fds[cfd].fd = -1;
                    fds[cfd].events = 0;
                    printf("client fd: %d disconnect\n",cfd);
                    close(cfd);
                    break;  //客戶端斷開連接
                }

                printf("recv cfd: %d data: %s\n",cfd,data);

                send(cfd,data,recvLen,0);
            }
        }
    }
    
    return 0;
}

epoll 操作流程

  1. 創(chuàng)建 epoll 實(shí)例。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  2. 準(zhǔn)備需要監(jiān)聽的文件描述符集合并添加到 epoll 實(shí)例中。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  3. 設(shè)置超時(shí)時(shí)間(可選)。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  4. 調(diào)用?epoll_wait?函數(shù)等待就緒事件。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  5. 檢查?epoll_wait?函數(shù)的返回值。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)
  6. 移除文件描述符或關(guān)閉 epoll 實(shí)例(可選)。【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端,網(wǎng)絡(luò)IO管理,架構(gòu),tcp/ip,網(wǎng)絡(luò)

注意事項(xiàng)

  • 在使用?epoll?函數(shù)之前,需要設(shè)置文件描述符的阻塞或非阻塞狀態(tài)。
  • 每次調(diào)用?epoll_wait?函數(shù)之前,需要重新設(shè)置需要監(jiān)聽的文件描述符集合,或是通過?epoll_ctl?函數(shù)動(dòng)態(tài)改變監(jiān)聽的文件描述符集合。
  • epoll?提供了更高效的事件通知機(jī)制,可以同時(shí)監(jiān)聽大量的文件描述符。
  • epoll_wait?函數(shù)將就緒的文件描述符信息填充到?events?數(shù)組中,可以通過遍歷數(shù)組來處理就緒事件。

總結(jié)

  • 通過調(diào)用?epoll_create 創(chuàng)建 epoll 實(shí)例,準(zhǔn)備需要監(jiān)聽的文件描述符集合并添加到 epoll 實(shí)例中,調(diào)用?epoll_wait?函數(shù)等待就緒事件,然后根據(jù)返回值和遍歷就緒事件集合來執(zhí)行相應(yīng)的 I/O 操作。最后,根據(jù)需要,可以移除文件描述符或關(guān)閉 epoll 實(shí)例。

epoll 完整代碼

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/epoll.h>


#define BUFFER_LENGTH   1024
#define EPOLL_LENGTH    1024

int init_server(int port){
    //獲取服務(wù)端fd,通常為3,前面0,1,2用于指定輸入,輸出,錯(cuò)誤值
    int sfd = socket(AF_INET,SOCK_STREAM,0);

    if(-1 == sfd){
        printf("socket error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    //設(shè)置服務(wù)端套接字為非阻塞模式
    // int flags = fcntl(sfd,F_GETFL,0);
    // fcntl(sfd,F_SETFL,flags | O_NONBLOCK);
    
    struct sockaddr_in servAddr;
    memset(&servAddr,0,sizeof(struct sockaddr_in));
    servAddr.sin_family = AF_INET;  //ipv4
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);   //0.0.0.0
    servAddr.sin_port = htons(port);
    
    //綁定IP和端口號(hào)
    if(-1 == bind(sfd,(struct sockaddr*)&servAddr,sizeof(struct sockaddr_in)))
    {
        printf("bind error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    //監(jiān)聽該套接字上的連接
    if(-1 == listen(sfd,10))
    {
        printf("listen error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    return sfd;
}

int main(int argc,char *argv[]){

    if(argc < 2)return -1;

    int port = atoi(argv[1]);
    int sfd = init_server(port);
    printf("server fd: %d\n",sfd);


    int epfd = epoll_create(1);     //在內(nèi)核創(chuàng)建epoll對(duì)象,在內(nèi)核中分配并初始化一個(gè)用于存儲(chǔ)事件的鏈表數(shù)據(jù)結(jié)構(gòu)
    printf("epoll fd: %d\n",epfd);
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = sfd;

    epoll_ctl(epfd,EPOLL_CTL_ADD,sfd,&event);   //往epoll實(shí)例中添加服務(wù)端文件描述符和對(duì)應(yīng)的事件

    struct epoll_event events[EPOLL_LENGTH] = {0};

    struct sockaddr_in clientAddr;
    socklen_t len = sizeof(struct sockaddr_in);
    while (1)   //mainloop 7*24小時(shí)工作
    {
        int nready = epoll_wait(epfd,events,EPOLL_LENGTH,-1);   //無限等待就緒事件的發(fā)生
        if(nready < 0)continue;

        int i = 0;
        for (i = 0; i < nready; i++)
        {
            int connfd = events[i].data.fd;

            if(sfd == connfd)
            {  //執(zhí)行accept操作,處理新的連接請(qǐng)求
                int cfd = accept(sfd,(struct sockaddr*)&clientAddr,&len);
                if(cfd < 0)continue;

                printf("client fd: %d\n",cfd);
                event.events = EPOLLIN;
                event.data.fd = cfd;
                epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&event);   //往epoll實(shí)例中添加客戶端文件描述符和對(duì)應(yīng)的事件
            }
            else if(events[i].events & EPOLLIN)
            {   //處理客戶端發(fā)送的數(shù)據(jù)
                char buffer[BUFFER_LENGTH] = {0};
                int recvLen = recv(connfd,buffer,BUFFER_LENGTH,0);
                if(recvLen > 0){
                    printf("recv client fd %d data: %s\n",connfd,buffer);

                    send(connfd,buffer,recvLen,0);
                }else if(recvLen == 0)
                {
                    printf("client fd %d close\n",connfd);

                    epoll_ctl(epfd,EPOLL_CTL_DEL,connfd,&event);   //在epoll實(shí)例中移除斷開的客戶端文件描述符和對(duì)應(yīng)的事件
                    close(connfd);
                }
            }
        }
    }
    
    return 0;
}

到了這里,關(guān)于【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八)

    linux并發(fā)服務(wù)器 —— IO多路復(fù)用(八)

    半關(guān)閉只能實(shí)現(xiàn)數(shù)據(jù)單方向的傳輸;當(dāng)TCP 接中A向 B 發(fā)送 FIN 請(qǐng)求關(guān)閉,另一端 B 回應(yīng)ACK 之后 (A 端進(jìn)入 FIN_WAIT_2 狀態(tài)),并沒有立即發(fā)送 FIN 給 A,A 方處于半連接狀態(tài) (半開關(guān)),此時(shí) A 可以接收 B 發(fā)送的數(shù)據(jù),但是 A 已經(jīng)不能再向 B 發(fā)送數(shù)據(jù) close不會(huì)影響到其他進(jìn)程,shutdown會(huì)

    2024年02月09日
    瀏覽(21)
  • 【高并發(fā)服務(wù)器 02】——線程池與IO多路復(fù)用

    線程池的好處 :所有的池都是為了事先把資源準(zhǔn)備好,在后續(xù)用的時(shí)候可以更加方便的拿到這個(gè)資源—— 不用去申請(qǐng)、釋放資源 什么時(shí)候用線程池 ? IO事務(wù)并發(fā)較高 :人在杭州,但是數(shù)據(jù)庫在北京,想要查詢數(shù)據(jù)庫,需要通過互聯(lián)網(wǎng)建立TCP三次握手,頻繁地創(chuàng)建和銷毀線

    2024年03月23日
    瀏覽(24)
  • Linux TCP/UDP socket 通信和IO多路復(fù)用

    主機(jī)字節(jié)序 16 位值 == 網(wǎng)絡(luò)字節(jié)序 16 位值 主機(jī)字節(jié)序 32 位值 == 網(wǎng)絡(luò)字節(jié)序 32 位值 主機(jī)字節(jié)序的字符串IP地址? == 網(wǎng)絡(luò)字節(jié)序的整形IP地址 將監(jiān)聽的套接字和本地IP和端口進(jìn)行關(guān)聯(lián) 給監(jiān)聽的套接字設(shè)置監(jiān)聽,開始檢測(cè)客戶端鏈接 等待并接受客戶端的連接,阻塞函數(shù),沒有客

    2024年02月05日
    瀏覽(25)
  • 【網(wǎng)絡(luò)編程】IO多路復(fù)用

    【網(wǎng)絡(luò)編程】IO多路復(fù)用

    ????????IO多路復(fù)用是一種高效的I/O處理方式,它 允許單個(gè)進(jìn)程能夠同時(shí)監(jiān)視多個(gè)文件描述符 (sockets、文件等),并在其中任何一個(gè)文件描述符準(zhǔn)備好進(jìn)行I/O操作時(shí)進(jìn)行處理。它的核心在于 使用少量的線程或進(jìn)程來管理多個(gè)I/O操作,以提高系統(tǒng)的性能和響應(yīng)速度 。 1.

    2024年02月09日
    瀏覽(25)
  • 網(wǎng)絡(luò)模型與 IO 多路復(fù)用

    網(wǎng)絡(luò)模型與 IO 多路復(fù)用

    ??socket也稱作“套接字”,用于描述IP地址和端口,是一個(gè)通信鏈路的描述符。應(yīng)用程序通常通過“套接字”向?qū)Χ税l(fā)出請(qǐng)求或者應(yīng)答網(wǎng)絡(luò)請(qǐng)求。 ??socket是連接運(yùn)行在網(wǎng)絡(luò)上的兩個(gè)程序之間的通信端點(diǎn)。通信的兩端都有socket,它是一個(gè)通道,數(shù)據(jù)在兩個(gè)socket之間進(jìn)行傳輸

    2024年02月01日
    瀏覽(28)
  • 使用Linux系統(tǒng)IO多路復(fù)用中eopll創(chuàng)建基于TCP通信協(xié)議的多人聊天室

    一.1.搭建好TCP的通信模型 2.創(chuàng)建紅黑樹根節(jié)點(diǎn)?3.將套接字事件添加到紅黑樹中,使其被監(jiān)聽 4.當(dāng)套接字事件發(fā)生,表示有客戶端連接,將連接事件加入到紅黑樹節(jié)點(diǎn)當(dāng)中 5.每當(dāng)連接事件發(fā)生時(shí),表示客戶端發(fā)送信息到服務(wù)器 6.每當(dāng)有事件準(zhǔn)備就緒時(shí),將對(duì)應(yīng)的紅黑樹節(jié)點(diǎn)信息

    2024年02月13日
    瀏覽(19)
  • 網(wǎng)絡(luò)編程 IO多路復(fù)用 [epoll版] (TCP網(wǎng)絡(luò)聊天室)

    網(wǎng)絡(luò)編程 IO多路復(fù)用 [epoll版] (TCP網(wǎng)絡(luò)聊天室)

    //head.h? ? ? ? ? ? 頭文件 //TcpGrpSer.c? ? ?服務(wù)器端 //TcpGrpUsr.c? ? ?客戶端 通過IO多路復(fù)用實(shí)現(xiàn)服務(wù)器在單進(jìn)程單線程下可以與多個(gè)客戶端交互 ?API epoll函數(shù) ?head.h TcpGrpSer.c TcpGrpUsr.c ?

    2024年02月11日
    瀏覽(24)
  • 網(wǎng)絡(luò)編程 IO多路復(fù)用 [select版] (TCP網(wǎng)絡(luò)聊天室)

    網(wǎng)絡(luò)編程 IO多路復(fù)用 [select版] (TCP網(wǎng)絡(luò)聊天室)

    //head.h? ? ? ? ? ? ? ? ?頭文件 //TcpGrpSer.c? ? ? ? 服務(wù)器端 //TcpGrpUsr.c? ? ? ? 客戶端 select函數(shù)? 功能:阻塞函數(shù),讓內(nèi)核去監(jiān)測(cè)集合中的文件描述符是否準(zhǔn)備就緒,若準(zhǔn)備就緒則解除阻塞。 原型: head.h TcpGrpSer.c TcpGrpUsr.c ? ?

    2024年02月14日
    瀏覽(24)
  • BIO、NIO、IO多路復(fù)用模型詳細(xì)介紹&Java NIO 網(wǎng)絡(luò)編程

    BIO、NIO、IO多路復(fù)用模型詳細(xì)介紹&Java NIO 網(wǎng)絡(luò)編程

    上文介紹了網(wǎng)絡(luò)編程的基礎(chǔ)知識(shí),并基于 Java 編寫了 BIO 的網(wǎng)絡(luò)編程。我們知道 BIO 模型是存在巨大問題的,比如 C10K 問題,其本質(zhì)就是因其阻塞原因,導(dǎo)致如果想要承受更多的請(qǐng)求就必須有足夠多的線程,但是足夠多的線程會(huì)帶來內(nèi)存占用問題、CPU上下文切換帶來的性能問題

    2024年02月14日
    瀏覽(29)
  • 08 - 網(wǎng)絡(luò)通信優(yōu)化之IO模型:如何解決高并發(fā)下IO瓶頸?

    08 - 網(wǎng)絡(luò)通信優(yōu)化之IO模型:如何解決高并發(fā)下IO瓶頸?

    提到 Java I/O,相信你一定不陌生。你可能使用 I/O 操作讀寫文件,也可能使用它實(shí)現(xiàn) Socket 的信息傳輸…這些都是我們?cè)谙到y(tǒng)中最常遇到的和 I/O 有關(guān)的操作。 我們都知道,I/O 的速度要比內(nèi)存速度慢,尤其是在現(xiàn)在這個(gè)大數(shù)據(jù)時(shí)代背景下,I/O 的性能問題更是尤為突出,I/O 讀寫

    2024年02月12日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包