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

【TCP服務(wù)器的演變過程】使用IO多路復(fù)用器epoll實(shí)現(xiàn)TCP服務(wù)器

這篇具有很好參考價(jià)值的文章主要介紹了【TCP服務(wù)器的演變過程】使用IO多路復(fù)用器epoll實(shí)現(xiàn)TCP服務(wù)器。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、前言

手把手教你從0開始編寫TCP服務(wù)器程序,體驗(yàn)開局一塊磚,大廈全靠壘。

為了避免篇幅過長使讀者感到乏味,對(duì)【TCP服務(wù)器的開發(fā)】進(jìn)行分階段實(shí)現(xiàn),一步步進(jìn)行優(yōu)化升級(jí)。
本節(jié),在上一章節(jié)的基礎(chǔ)上,將IO多路復(fù)用機(jī)制select改為更高效的IO多路復(fù)用機(jī)制epoll,使用epoll管理每個(gè)新接入的客戶端連接,實(shí)現(xiàn)發(fā)送和接收。

epoll是Linux內(nèi)核中一種可擴(kuò)展的IO事件處理機(jī)制,可替代select和poll的系統(tǒng)調(diào)用。處理百萬級(jí)并發(fā)訪問性能更佳。

select的局限性:

(1) 文件描述符越多,性能越差。 單個(gè)進(jìn)程中能夠監(jiān)視的文件描述符存在最大的數(shù)量,默認(rèn)是1024(在linux內(nèi)核頭文件中定義有 #define _FD_SETSIZE 1024),當(dāng)然也可以修改,但是文件描述符數(shù)量越多,性能越差。

(2)開銷巨大 ,select需要復(fù)制大量的句柄數(shù)據(jù)結(jié)構(gòu),產(chǎn)生了巨大的開銷(內(nèi)核/用戶空間內(nèi)存拷貝問題)。

(3)select需要遍歷整個(gè)句柄數(shù)組才能知道哪些句柄有事件。

(4)如果沒有完成對(duì)一個(gè)已經(jīng)就緒的文件描述符的IO操作,那么每次調(diào)用select還是會(huì)將這些文件描述符通知進(jìn)程,即水平觸發(fā)。

(5)poll使用鏈表保存監(jiān)視的文件描述符,雖然沒有了監(jiān)視文件數(shù)量的限制,但是其他缺點(diǎn)依舊存在。

由于以上缺點(diǎn),基于select模型的服務(wù)器程序,要達(dá)到十萬以上的并發(fā)訪問,是很難完成的。因此,epoll出場了。
【TCP服務(wù)器的演變過程】使用IO多路復(fù)用器epoll實(shí)現(xiàn)TCP服務(wù)器,Linux網(wǎng)絡(luò)設(shè)計(jì),tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),linux,運(yùn)維,c語言

二、新增使用API函數(shù)

2.1、epoll_create()函數(shù)

函數(shù)原型:

#include <sys/epoll.h>
int epoll_create(int size);

功能:創(chuàng)建epoll的文件描述符。

參數(shù)說明:size表示內(nèi)核需要監(jiān)控的最大數(shù)量,但是這個(gè)參數(shù)內(nèi)核已經(jīng)不會(huì)用到,只要傳入一個(gè)大于0的值即可。 當(dāng)size<=0時(shí),會(huì)直接返回不可用,這是歷史原因保留下來的,最早的epoll_create是需要定義一次性就緒的最大數(shù)量;后來使用了鏈表以便便維護(hù)和擴(kuò)展,就不再需要使用傳入的參數(shù)。

返回:返回該對(duì)象的描述符,注意要使用 close 關(guān)閉該描述符。

2.2、epoll_ctl()函數(shù)

函數(shù)原型:

#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
// epoll_ctl對(duì)應(yīng)系統(tǒng)調(diào)用sys_epoll_ctl

功能:操作epoll的文件描述符,主要是對(duì)epoll的紅黑樹節(jié)點(diǎn)進(jìn)行操作,比如節(jié)點(diǎn)的增刪改查。
參數(shù)說明:

參數(shù) 含義
epfd 通過 epoll_create 創(chuàng)建的文件描述符
op 對(duì)紅黑樹的操作,比如節(jié)點(diǎn)的增加、修改、刪除,分別對(duì)應(yīng)EPOLL_CTL_ADD、EPOLL_CTL_MOD、EPOLL_CTL_DEL
fd 需要添加監(jiān)聽的文件描述符
event 事件信息

注意:epoll_ctl是非阻塞的,不會(huì)被掛起。

2.3、struct epoll_event結(jié)構(gòu)體

struct epoll_event結(jié)構(gòu)體原型:

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

struct epoll_event{
	uint32_t events;
	epoll_data_t data;
}

events成員代表要監(jiān)聽的epoll事件類型

events成員:

成員變量 含義
EPOLLIN 監(jiān)聽fd的讀事件
EPOLLOUT 監(jiān)聽fd的寫事件
EPOLLRI 監(jiān)聽緊急數(shù)據(jù)可讀事件(帶外數(shù)據(jù)到來)
EPOLLRDHUP 監(jiān)聽套接字關(guān)閉或半關(guān)閉事件
EPOLLET 將EPOLL設(shè)為邊緣觸發(fā)(Edge Triggered)模式

data成員:

data 成員時(shí)一個(gè)聯(lián)合體類型,可以在調(diào)用 epoll_ctl 給 fd 添加/修改描述符監(jiān)聽的事件時(shí)攜帶一些數(shù)據(jù),方便后面的epoll_wait可以取出信息使用。

2.4、epoll_wait()函數(shù)

函數(shù)原型:

#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

功能:阻塞一段時(shí)間,等待事件發(fā)生
返回:返回事件數(shù)量,事件集添加到events數(shù)組中。也就是遍歷紅黑樹中的雙向鏈表,把雙向鏈表中的節(jié)點(diǎn)數(shù)據(jù)拷貝出來,拷貝完畢后把節(jié)點(diǎn)從雙向鏈表中移除。

返回值 含義
大于0 事件個(gè)數(shù)
等于0 超時(shí)時(shí)間timeout到了
小于0 出錯(cuò),可通過errno查看出錯(cuò)原因

參數(shù)說明:

參數(shù) 含義
epfd 通過 epoll_create 創(chuàng)建的文件描述符
events 存放就緒的事件集合,是輸出參數(shù)
maxevents 最大可存放事件數(shù)量,events數(shù)組大小
timeout 阻塞等待的時(shí)間長短,單位是毫秒,-1表示一直阻塞等待

三、實(shí)現(xiàn)步驟

epoll的優(yōu)點(diǎn):

  • 不需要輪詢所有的文件描述符。
  • 每次取就緒集合,都在固定位置。
  • 事件的就緒和IO觸發(fā)可以異步解耦。

(1)創(chuàng)建socket。

int listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd==-1){
    printf("errno = %d, %s\n",errno,strerror(errno));
    return SOCKET_CREATE_FAILED;
}

(2)綁定地址。

struct sockaddr_in server;
memset(&server,0,sizeof(server));

server.sin_family=AF_INET;
server.sin_addr.s_addr=htonl(INADDR_ANY);
server.sin_port=htons(LISTEN_PORT);

if(-1==bind(listenfd,(struct sockaddr*)&server,sizeof(server))){
    printf("errno = %d, %s\n",errno,strerror(errno));
    close(listenfd);
    return SOCKET_BIND_FAILED;
}

(3)設(shè)置監(jiān)聽。

if(-1==listen(listenfd,BLOCK_SIZE)){
   printf("errno = %d, %s\n",errno,strerror(errno));
   close(listenfd);
   return SOCKET_LISTEN_FAILED;
}

(4)創(chuàng)建epoll。

int epfd=epoll_create(1);
if(epfd==-1)
{
    perror("epoll_create error");
    return SOCKET_EPOLL_CREATE_FAILED;
}

(5)添加listen fd 到epoll。

struct epoll_event ev;
ev.events=EPOLLIN;
ev.data.fd=listenfd;

if(epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev)==-1)
{
    perror("epoll_ctl error");
    return SOCKET_EPOLL_CTL_FAILED;
}

(6)監(jiān)聽事件。

int nready=epoll_wait(epfd,evs,EVENTS_LENGTH,-1);

(7)如果監(jiān)聽套接字有新連接請(qǐng)求,處理新連接。

int curfd=evs[i].data.fd;
if(curfd==listenfd)
{
    // accept
    struct sockaddr_in client;
    socklen_t clientlen=sizeof(client);
    int clientfd=accept(listenfd,(struct sockaddr*)&client,&clientlen);
    if(clientfd==-1)
    {
        perror("accept error");
        continue;
    }
    //printf("client %s:%d connected\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
    printf("client %s:%d connected\n", inet_ntoa(client.sin_addr),ntohs(client.sin_port));
    ev.events=EPOLLIN;
    ev.data.fd=clientfd;
    if(epoll_ctl(epfd,EPOLL_CTL_ADD,clientfd,&ev)==-1)
    {
        perror("epoll_ctl error");
        exit(SOCKET_EPOLL_CTL_FAILED);
    }

}

(8)處理客戶端發(fā)來的數(shù)據(jù)和發(fā)送數(shù)據(jù)到客戶端。

if(evs[i].events&EPOLLIN)
{
    //read
    int ret=recv(curfd,rbuff,BUFFER_LENGTH,0);
    if(ret>0)
    {
        printf("recv from %d: %s\n",curfd,rbuff);
        rbuff[ret]='\0';
        memcpy(wbuff,rbuff,BUFFER_LENGTH);
        ev.events=EPOLLOUT;
        ev.data.fd=curfd;
        if(epoll_ctl(epfd,EPOLL_CTL_MOD,curfd,&ev)==-1)
        {
            perror("epoll_ctl error");
            exit(SOCKET_EPOLL_CTL_FAILED);
        }
    }
    else if(ret==0)// 連接關(guān)閉
    {
        printf("client %d disconnected\n", evs[i].data.fd);
        

        // 將連接從epoll實(shí)例中刪除
        
        if(epoll_ctl(epfd, EPOLL_CTL_DEL, evs[i].data.fd, NULL)==-1)
        {
            perror("epoll_ctl error");
            exit(SOCKET_EPOLL_CTL_FAILED);
        }
        close(evs[i].data.fd);
    }
    else if (ret == -1) {
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            continue; // 數(shù)據(jù)已讀完
        }
        perror("read error");
        break;
    } 
    else{
        printf("read error,unknow type %d\n",ret);
    }

}
else if(evs[i].events&EPOLLOUT)
{
    //write
    send(curfd,wbuff,BUFFER_LENGTH,0);
    ev.events=EPOLLIN;
    ev.data.fd=curfd;
    if(epoll_ctl(epfd,EPOLL_CTL_MOD,curfd,&ev)==-1)
    {
        perror("epoll_ctl error");
        exit(SOCKET_EPOLL_CTL_FAILED);
    }
}

四、完整代碼

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

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

#include <sys/epoll.h>

#define LISTEN_PORT     9999
#define BLOCK_SIZE      10
#define BUFFER_LENGTH   1024
#define EVENTS_LENGTH   128

enum ERROR_CODE{
    SOCKET_CREATE_FAILED=-1,
    SOCKET_BIND_FAILED=-2,
    SOCKET_LISTEN_FAILED=-3,
    SOCKET_ACCEPT_FAILED=-4,
    SOCKET_SELECT_FAILED=-5,
    SOCKET_EPOLL_CREATE_FAILED=-6,
    SOCKET_EPOLL_CTL_FAILED=-7,
    SOCKET_EPOLL_WAIT_FAILED=-8
};

char rbuff[BUFFER_LENGTH] = { 0 };
char wbuff[BUFFER_LENGTH] = { 0 };

int main(int argc,char **argv)
{
    // 1.
    int listenfd=socket(AF_INET,SOCK_STREAM,0);
    if(listenfd==-1){
        printf("errno = %d, %s\n",errno,strerror(errno));
        return SOCKET_CREATE_FAILED;
    }

    // 2.
    struct sockaddr_in server;
    memset(&server,0,sizeof(server));

    server.sin_family=AF_INET;
    server.sin_addr.s_addr=htonl(INADDR_ANY);
    server.sin_port=htons(LISTEN_PORT);

    if(-1==bind(listenfd,(struct sockaddr*)&server,sizeof(server))){
        printf("errno = %d, %s\n",errno,strerror(errno));
        close(listenfd);
        return SOCKET_BIND_FAILED;
    }

    // 3.
    if(-1==listen(listenfd,BLOCK_SIZE)){
        printf("errno = %d, %s\n",errno,strerror(errno));
        close(listenfd);
        return SOCKET_LISTEN_FAILED;
    }

    printf("listen port: %d\n",LISTEN_PORT);
    
    // 4.
    int epfd=epoll_create(1);
    if(epfd==-1)
    {
        perror("epoll_create error");
        return SOCKET_EPOLL_CREATE_FAILED;
    }
    struct epoll_event ev,evs[EVENTS_LENGTH];
    ev.events=EPOLLIN;
    ev.data.fd=listenfd;
    
    if(epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev)==-1)
    {
        perror("epoll_ctl error");
        return SOCKET_EPOLL_CTL_FAILED;
    }
    printf("start epoll_wait. epoll fd = %d\n",epfd);
    while(1)
    {
        int nready=epoll_wait(epfd,evs,EVENTS_LENGTH,-1);
        
        if (nready == -1) {
            perror("epoll_wait error");
            exit(SOCKET_EPOLL_WAIT_FAILED);
        }
        for(int i=0;i<nready;i++)
        {
            int curfd=evs[i].data.fd;
            if(curfd==listenfd)
            {
                // accept
                struct sockaddr_in client;
                socklen_t clientlen=sizeof(client);
                int clientfd=accept(listenfd,(struct sockaddr*)&client,&clientlen);
                if(clientfd==-1)
                {
                    perror("accept error");
                    continue;
                }
                //printf("client %s:%d connected\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
                printf("client %s:%d connected\n", inet_ntoa(client.sin_addr),ntohs(client.sin_port));
                ev.events=EPOLLIN;
                ev.data.fd=clientfd;
                if(epoll_ctl(epfd,EPOLL_CTL_ADD,clientfd,&ev)==-1)
                {
                    perror("epoll_ctl error");
                    exit(SOCKET_EPOLL_CTL_FAILED);
                }

            }
            else if(evs[i].events&EPOLLIN)
            {
                //read
                int ret=recv(curfd,rbuff,BUFFER_LENGTH,0);
                if(ret>0)
                {
                    printf("recv from %d: %s\n",curfd,rbuff);
                    rbuff[ret]='\0';
                    memcpy(wbuff,rbuff,BUFFER_LENGTH);
                    ev.events=EPOLLOUT;
                    ev.data.fd=curfd;
                    if(epoll_ctl(epfd,EPOLL_CTL_MOD,curfd,&ev)==-1)
                    {
                        perror("epoll_ctl error");
                        exit(SOCKET_EPOLL_CTL_FAILED);
                    }
                }
                else if(ret==0)// 連接關(guān)閉
                {
                    printf("client %d disconnected\n", evs[i].data.fd);
                    

                    // 將連接從epoll實(shí)例中刪除
                    
                    if(epoll_ctl(epfd, EPOLL_CTL_DEL, evs[i].data.fd, NULL)==-1)
                    {
                        perror("epoll_ctl error");
                        exit(SOCKET_EPOLL_CTL_FAILED);
                    }
                    close(evs[i].data.fd);
                }
                else if (ret == -1) {
                    if (errno == EAGAIN || errno == EWOULDBLOCK) {
                        continue; // 數(shù)據(jù)已讀完
                    }
                    perror("read error");
                    break;
                } 
                else{
                    printf("read error,unknow type %d\n",ret);
                }

            }
            else if(evs[i].events&EPOLLOUT)
            {
                //write
                send(curfd,wbuff,BUFFER_LENGTH,0);
                ev.events=EPOLLIN;
                ev.data.fd=curfd;
                if(epoll_ctl(epfd,EPOLL_CTL_MOD,curfd,&ev)==-1)
                {
                    perror("epoll_ctl error");
                    exit(SOCKET_EPOLL_CTL_FAILED);
                }
            }
        }
    }
    
    close(listenfd);

    return 0;
}

編譯命令:

gcc -o server server.c

五、TCP客戶端

5.1、自己實(shí)現(xiàn)一個(gè)TCP客戶端

自己實(shí)現(xiàn)一個(gè)TCP客戶端連接TCP服務(wù)器的代碼:

#include <stdio.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <arpa/inet.h>

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

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

#define BUFFER_LENGTH   1024

enum ERROR_CODE{
    SOCKET_CREATE_FAILED=-1,
    SOCKET_CONN_FAILED=-2,
    SOCKET_LISTEN_FAILED=-3,
    SOCKET_ACCEPT_FAILED=-4
};

int main(int argc,char** argv)
{
    if(argc<3)
    {
        printf("Please enter the server IP and port.");
        return 0;
    }
    printf("connect to %s, port=%s\n",argv[1],argv[2]);

    int connfd=socket(AF_INET,SOCK_STREAM,0);
    if(connfd==-1)
    {
        printf("errno = %d, %s\n",errno,strerror(errno));
        return SOCKET_CREATE_FAILED;

    }
    struct sockaddr_in serv;
    serv.sin_family=AF_INET;
    serv.sin_addr.s_addr=inet_addr(argv[1]);
    serv.sin_port=htons(atoi(argv[2]));
    socklen_t len=sizeof(serv);
    int rwfd=connect(connfd,(struct sockaddr*)&serv,len);
    if(rwfd==-1)
    {
        printf("errno = %d, %s\n",errno,strerror(errno));
        close(rwfd);
        return SOCKET_CONN_FAILED;
    }
    int ret=1;
    while(ret>0)
    {
        char buf[BUFFER_LENGTH]={0};
        printf("Please enter the string to send:\n");
        scanf("%s",buf);
        send(connfd,buf,strlen(buf),0);

        memset(buf,0,BUFFER_LENGTH);
        printf("recv:\n");
        ret=recv(connfd,buf,BUFFER_LENGTH,0);
        printf("%s\n",buf);
        
    }
    close(rwfd);
    return 0;
}

編譯:

gcc -o client client.c

5.2、Windows下可以使用NetAssist的網(wǎng)絡(luò)助手工具

【TCP服務(wù)器的演變過程】使用IO多路復(fù)用器epoll實(shí)現(xiàn)TCP服務(wù)器,Linux網(wǎng)絡(luò)設(shè)計(jì),tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),linux,運(yùn)維,c語言
下載地址:http://old.tpyboard.com/downloads/NetAssist.exe

小結(jié)

至此,我們最終確定使用IO多路復(fù)用器epoll處理高并發(fā)。但是,上面的epoll實(shí)現(xiàn)的TCP服務(wù)器存在一些問題:

  1. 所有的連接都是使用相同的讀寫緩存(rbuff和wbuff),這會(huì)導(dǎo)致數(shù)據(jù)覆蓋。
  2. 沒有分包能力。

下一章節(jié)會(huì)解決這些問題,構(gòu)建一個(gè)reactor網(wǎng)絡(luò)模型。

【TCP服務(wù)器的演變過程】使用IO多路復(fù)用器epoll實(shí)現(xiàn)TCP服務(wù)器,Linux網(wǎng)絡(luò)設(shè)計(jì),tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),linux,運(yùn)維,c語言文章來源地址http://www.zghlxwxcb.cn/news/detail-797716.html

到了這里,關(guān)于【TCP服務(wù)器的演變過程】使用IO多路復(fù)用器epoll實(shí)現(xiàn)TCP服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(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)文章

  • TCP服務(wù)器的演變過程:多進(jìn)程實(shí)現(xiàn)一對(duì)多的TCP服務(wù)器

    TCP服務(wù)器的演變過程:多進(jìn)程實(shí)現(xiàn)一對(duì)多的TCP服務(wù)器

    手把手教你從0開始編寫TCP服務(wù)器程序,體驗(yàn)開局一塊磚,大廈全靠壘。 為了避免篇幅過長使讀者感到乏味,對(duì)【TCP服務(wù)器的開發(fā)】進(jìn)行分階段實(shí)現(xiàn),一步步進(jìn)行優(yōu)化升級(jí)。本節(jié)在上一章節(jié)的基礎(chǔ)上,改為多進(jìn)程方式實(shí)現(xiàn)TCP服務(wù)器,為每個(gè)新接入的客戶端分配進(jìn)程,實(shí)現(xiàn)一個(gè)

    2024年02月04日
    瀏覽(22)
  • TCP服務(wù)器的演變過程:使用epoll構(gòu)建reactor網(wǎng)絡(luò)模型實(shí)現(xiàn)百萬級(jí)并發(fā)(詳細(xì)代碼)

    TCP服務(wù)器的演變過程:使用epoll構(gòu)建reactor網(wǎng)絡(luò)模型實(shí)現(xiàn)百萬級(jí)并發(fā)(詳細(xì)代碼)

    手把手教你從0開始編寫TCP服務(wù)器程序,體驗(yàn)開局一塊磚,大廈全靠壘。 為了避免篇幅過長使讀者感到乏味,對(duì)【TCP服務(wù)器的開發(fā)】進(jìn)行分階段實(shí)現(xiàn),一步步進(jìn)行優(yōu)化升級(jí)。 本節(jié),在上一章節(jié)介紹了如何使用epoll開發(fā)高效的服務(wù)器,本節(jié)將介紹使用epoll構(gòu)建reactor網(wǎng)絡(luò)模型,實(shí)

    2024年02月01日
    瀏覽(30)
  • 【TCP服務(wù)器的演變過程】編寫第一個(gè)TCP服務(wù)器:實(shí)現(xiàn)一對(duì)一的連接通信

    【TCP服務(wù)器的演變過程】編寫第一個(gè)TCP服務(wù)器:實(shí)現(xiàn)一對(duì)一的連接通信

    手把手教你從0開始編寫TCP服務(wù)器程序,體驗(yàn) 開局一塊磚,大廈全靠壘 。 為了避免篇幅過長使讀者感到乏味,對(duì)【TCP服務(wù)器的開發(fā)】進(jìn)行分階段實(shí)現(xiàn),一步步進(jìn)行優(yōu)化升級(jí)。 函數(shù)原型: 這個(gè)函數(shù)建立一個(gè)協(xié)議族、協(xié)議類型、協(xié)議編號(hào)的socket文件描述符。如果函數(shù)調(diào)用成功,

    2024年02月03日
    瀏覽(23)
  • IO多路復(fù)用中select的TCP服務(wù)器模型和poll服務(wù)模型

    服務(wù)器端 客戶端 poll客戶端

    2024年02月12日
    瀏覽(31)
  • 【Linux網(wǎng)絡(luò)編程】TCP并發(fā)服務(wù)器的實(shí)現(xiàn)(IO多路復(fù)用select)

    【Linux網(wǎng)絡(luò)編程】TCP并發(fā)服務(wù)器的實(shí)現(xiàn)(IO多路復(fù)用select)

    服務(wù)器模型主要分為兩種, 循環(huán)服務(wù)器 和 并發(fā)服務(wù)器 。 循環(huán)服務(wù)器 : 在同一時(shí)間只能處理一個(gè)客戶端的請(qǐng)求。 并發(fā)服務(wù)器 : 在同一時(shí)間內(nèi)能同時(shí)處理多個(gè)客戶端的請(qǐng)求。 TCP的服務(wù)器默認(rèn)的就是一個(gè)循環(huán)服務(wù)器,原因是有兩個(gè)阻塞 accept函數(shù) 和recv函數(shù) 之間會(huì)相互影響。

    2024年02月03日
    瀏覽(100)
  • 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日
    瀏覽(22)
  • 【高并發(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)
  • 多路IO—POll函數(shù),epoll服務(wù)器開發(fā)流程

    多路IO—POll函數(shù),epoll服務(wù)器開發(fā)流程

    \\\"在計(jì)算機(jī)網(wǎng)絡(luò)編程中,多路IO技術(shù)是非常常見的一種技術(shù)。其中,Poll函數(shù)和Epoll函數(shù)是最為常用的兩種多路IO技術(shù)。這兩種技術(shù)可以幫助服務(wù)器端處理多個(gè)客戶端的并發(fā)請(qǐng)求,提高了服務(wù)器的性能。本文將介紹Poll和Epoll函數(shù)的使用方法,并探討了在服務(wù)器開發(fā)中使用這兩種技

    2024年02月06日
    瀏覽(18)
  • Linux多路IO復(fù)用技術(shù)——epoll詳解與一對(duì)多服務(wù)器實(shí)現(xiàn)

    Linux多路IO復(fù)用技術(shù)——epoll詳解與一對(duì)多服務(wù)器實(shí)現(xiàn)

    本文詳細(xì)介紹了Linux中epoll模型的優(yōu)化原理和使用方法,以及如何利用epoll模型實(shí)現(xiàn)簡易的一對(duì)多服務(wù)器。通過對(duì)epoll模型的優(yōu)化和相關(guān)接口的解釋,幫助讀者理解epoll模型的工作原理和優(yōu)缺點(diǎn),同時(shí)附帶代碼實(shí)現(xiàn)和圖解說明。

    2024年02月05日
    瀏覽(27)
  • 多路轉(zhuǎn)接高性能IO服務(wù)器|select|poll|epoll|模型詳細(xì)實(shí)現(xiàn)

    多路轉(zhuǎn)接高性能IO服務(wù)器|select|poll|epoll|模型詳細(xì)實(shí)現(xiàn)

    那么這里博主先安利一下一些干貨滿滿的專欄啦! Linux專欄 https://blog.csdn.net/yu_cblog/category_11786077.html?spm=1001.2014.3001.5482 操作系統(tǒng)專欄 https://blog.csdn.net/yu_cblog/category_12165502.html?spm=1001.2014.3001.5482 手撕數(shù)據(jù)結(jié)構(gòu) https://blog.csdn.net/yu_cblog/category_11490888.html?spm=1001.2014.3001.5482 去倉庫獲

    2024年02月15日
    瀏覽(25)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包