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

TCP高并發(fā)服務器簡介(select、poll、epoll實現與區(qū)別)

這篇具有很好參考價值的文章主要介紹了TCP高并發(fā)服務器簡介(select、poll、epoll實現與區(qū)別)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

select、poll、epoll三者的實現:

select實現TCP高并發(fā)服務器的流程:

  • 一、創(chuàng)建套接字(socket函數):
  • 二、填充服務器的網絡信息結構體:
  • 三、套接字和服務器的網絡信息結構體進行綁定(bind函數):
  • 四、套接字設置成被動監(jiān)聽(listen函數):
  • 五、創(chuàng)建要監(jiān)聽的文件描述符集合:
  • 使用select函數后,會將沒有就緒的文件描述符在集合中去除,所以需要創(chuàng)建兩個文件描述符集合,一個是母本read_fds,類似于常量,保持不變,而另一個作為副本read_fds_t,類似于變量,可以改變;
	fd_set read_fds;
    FD_ZERO(&read_fds);
    fd_set read_fds_t;
    FD_ZERO(&read_fds_t);
  • 六、把創(chuàng)建的套接字添加到要監(jiān)視的集合中:
	FD_SET(sockfd,&read_fds);
    int fd_max = 0;
    fd_max = fd_max > sockfd ? fd_max : sockfd;
  • 七、設置系統(tǒng)時間結構體變量,用來指定超時的時間:
	struct timeval tm_out;
  • 八、等待文件描述符中的事件是否就緒,成功則返回就緒的文件描述符的個數(select函數):
  • select函數:
	#include <sys/select.h>
	int select(int nfds, fd_set *readfds, fd_set *writefds,
                fd_set *exceptfds, struct timeval *timeout);
    /*
	參數:
		nfds:		要監(jiān)視的最大文件描述符+1
	
		readfds:	要監(jiān)視的讀文件描述符集合 不關心可以傳NULL
	
		writefds:	要監(jiān)視的寫文件描述符集合 不關心可以傳NULL
	
		exceptfds:	要監(jiān)視的異常文件描述符集合 不關心可以傳NULL
	
		timeout:	超時時間 如果設置成NULL 會一直阻塞 直到有文件描述符就緒
					
	返回值:
	
		成功 就緒的文件描述符的個數
	
		超時 0
	
		失敗 -1 重置錯誤碼
	 */
	 				//struct timeval  可以指定超時時間

				    //如果結構體的兩個成員都為0 表示非阻塞
				    
				    struct timeval {
				        long    tv_sec;         //秒 
				        long    tv_usec;       //微秒
				    };
				    
		void FD_CLR(int fd, fd_set *set);	//將文件描述符在集合中刪除
		
		int  FD_ISSET(int fd, fd_set *set);	//判斷文件描述符是否還在集合中
							// 返回0 表示不在了 非0 表示在
		void FD_SET(int fd, fd_set *set);	//向集合中添加一個文件描述符
		
		void FD_ZERO(fd_set *set);			//清空集合

		if(-1 == (ret = select(fd_max + 1,&read_fds_t,NULL,NULL,&tm_out)))
        {
            perror("select error");
            exit(-1);
        }
        else if(0 == ret)
        {
            puts("timeout!!!!!");
            putchar('\n');
            continue;
        }
  • 九、遍歷文件描述符集合,判斷哪些文件描述符已經準備就緒:
		for(int i = 3; i < fd_max + 1 && 0 != ret; i++)
        {
				...
		}
  • 十、判斷文件描述符是否還在集合中,并且接收來自客戶端的數據(recv函數)和給客戶端發(fā)送應答消息(send函數):
            if(FD_ISSET(i,&read_fds_t))
            {
                //說明有新的客戶端連接服務器
                if(i == sockfd)
                {   
                    
                    if(-1 == (accept_fd = accept(sockfd,NULL,NULL)))
                    {
                        perror("accept error");
                        exit(-1);
                    
                    }

                    printf("客戶端[%d]連接到服務器\n",accept_fd);

                    //將新連接的客戶端的套接字添加到要監(jiān)視的集合中
                    FD_SET(accept_fd,&read_fds);

                    fd_max = fd_max > accept_fd ? fd_max : accept_fd;
                }
                else //之前連接的客戶端在向服務器發(fā)送信息
                {

                    memset(buf,0,sizeof(buf));
                    if(-1 == (nbytes = recv(i,buf,sizeof(buf),0)))
                    {
                        perror("recv error");
                        exit(-1);
                    }
                    else if(0 == nbytes)
                    {
                        printf("客戶端[%d]已斷開連接\n",i);

                        //將已斷開連接客戶端的套接字在文件描述符集合中剔除
                        FD_CLR(i,&read_fds);

                        //關閉套接字
                        close(i);
                        continue;
                    }
                    if(!strncmp(buf,"quit",4))
                    {
                        printf("客戶端[%d]已退出\n",i);
                        //將已斷開連接客戶端的套接字在文件描述符集合中剔除
                        FD_CLR(i,&read_fds);

                        //關閉套接字
                        close(i);
                        continue;
                    }
                    printf("客戶端[%d]發(fā)來信息[%s]\n",i,buf);

                    //組裝應答消息
                    strcat(buf,"----------k");

                    //給客戶端發(fā)送應答消息
                    if(-1 == send(i,buf,sizeof(buf),0))
                    {
                        perror("send error");
                        exit(-1);
                    }

                }
                ret--; //減少遍歷次數
                
            }
  • 十一、關閉套接字(close函數):

poll實現TCP高并發(fā)服務器的流程:

  • 一、創(chuàng)建套接字(socket函數):
  • 二、填充服務器的網絡信息結構體:
  • 三、套接字和服務器的網絡信息結構體進行綁定(bind函數):
  • 四、套接字設置成被動監(jiān)聽(listen函數):
  • 五、創(chuàng)建要監(jiān)聽的文件描述符集合并清空文件描述符集合:
	//創(chuàng)建要監(jiān)聽的文件描述符集合
    struct pollfd new_fds[2048] = {0};
    
    //清空文件描述符集合
    for(int i = 0; i < 2048; ++i)
    {
        new_fds[i].fd = -1;
    }
  • 六、把創(chuàng)建的套接字添加到要監(jiān)視的集合中:
	FD_SET(sockfd,&read_fds);
    int fd_max = 0;
    fd_max = fd_max > sockfd ? fd_max : sockfd;
  • 七、套接字添加到要監(jiān)視的集合中,并且設置要監(jiān)聽的事件:
	//套接字添加到要監(jiān)視的集合中
    new_fds[0].fd = sockfd;

    //設置要監(jiān)聽的事件
    new_fds[0].events |= POLLIN;
  • 八、記錄文件描述符集合中最大的文件描述符,并且設置超時的時間:
	//記錄文件描述符集合中最大的文件描述符
    int fd_max = 0;
    fd_max = fd_max > sockfd ? fd_max : sockfd;

    //設置超時的時間
    int tm_out = 10000;
  • 九、等待文件描述符中的事件是否就緒,成功則返回就緒的文件描述符的個數(poll函數):
  • poll實現TCP中型并發(fā)服務器select實現TCP小型并發(fā)服務器區(qū)別就是無需每次重置集合,并且可以設置要監(jiān)視的最大文件描述符的個數,而select至多監(jiān)視1024個文件描述符;
  • poll函數:
	#include <poll.h>
	int poll(struct pollfd *fds, nfds_t nfds, int timeout);
	/*
	參數:
	
		fds:要監(jiān)視的文件描述符的集合指向自定義的結構體數據
		
		nfds:fds中已經使用的項目的個數
		
		timeout:超時時間單位是毫秒  
		
				設置成10000 表示10s
				
				-1	永久阻塞
				
				0	非阻塞
	返回值:
	
		0		超時
		-1		出錯 重置錯誤碼
		正數	成功 返回的就緒的文件描述符的個數
	*/
			struct pollfd {
			   int   fd;         /* 文件描述符 設置成-1 內核就不再監(jiān)視這一位了*/
			   short events;     /* 要監(jiān)視的事件 */
			   short revents;    /* 返回的事件 */
			};
			/*
			要監(jiān)視的事件是用位運算或起來的
			
			要監(jiān)視的事件放在events字段,而實際就緒的事件在revents字段返回
			
			POLLIN	讀事件
			
			POLLOUT	寫時間
			
			POLLERR	異常事件
			*/

		if(-1 == (ret = poll(new_fds,fd_max,tm_out)))
        {
            perror("poll error");
            exit(-1);
        }
        else if(0 == ret)
        {
            puts("timeout!!!!!");
            putchar('\n');
            continue;
        }
  • 十、遍歷文件描述符集合,判斷哪些文件描述符已經準備就緒:
		for(k = 0; k <= fd_max && ret != 0; ++k)
        {   
				...
		}
  • 十一、找到實際就緒的事件的文件描述符,并且接收來自客戶端的數據(recv函數)和給客戶端發(fā)送應答消息(send函數):
           //找到實際就緒的事件的文件描述符
            if(0 != (new_fds[k].revents & POLLIN))
            {
                //說明有新的客戶端連接服務器
                if(new_fds[k].fd == sockfd)
                {
                    if(-1 == (accept_fd = accept(sockfd,NULL,NULL)))
                    {
                        perror("accept error");
                        exit(-1);
                    
                    }

                    printf("客戶端[%d]連接到服務器\n",accept_fd);

                    //將新連接的客戶端的套接字添加到要監(jiān)視的集合中

                    //遍歷文件描述符集合,給新的文件描述符找一個位置
                    for(j = 0; j < 2048; j++)
                    {
                        if(-1 == new_fds[j].fd)
                        {
                            new_fds[j].fd = accept_fd;
                            new_fds[j].events |= POLLIN;

                            fd_max = fd_max > accept_fd ? fd_max : accept_fd;
                            break;
                        }
                    }
                    if(2048 == j)
                    {
                        //此時集合容量滿了
                        close(accept_fd);
                    }
                    

                }
                else //之前連接的客戶端在向服務器發(fā)送信息
                {

                    memset(buf,0,sizeof(buf));
                    if(-1 == (nbytes = recv(new_fds[k].fd,buf,sizeof(buf),0)))
                    {
                        perror("recv error");
                        exit(-1);
                    }
                    else if(0 == nbytes)
                    {
                        printf("客戶端[%d]已斷開連接\n",new_fds[k].fd);

                        //將已斷開連接客戶端的套接字在文件描述符集合中剔除
                        close(new_fds[k].fd);
                        new_fds[k].fd = -1;
                        continue;
                    }
                    if(!strncmp(buf,"quit",4))
                    {
                        printf("客戶端[%d]已退出\n",new_fds[k].fd);
                        //將已斷開連接客戶端的套接字在文件描述符集合中剔除
                        close(new_fds[k].fd);
                        new_fds[k].fd = -1;
                        continue;
                    }
                    printf("客戶端[%d]發(fā)來信息[%s]\n",new_fds[k].fd,buf);

                    //組裝應答消息
                    strcat(buf,"----------k");

                    //給客戶端發(fā)送應答消息
                    if(-1 == send(new_fds[k].fd,buf,sizeof(buf),0))
                    {
                        perror("send error");
                        exit(-1);
                    }

                }
                ret--; //減少遍歷次數
            }
  • 十二、關閉套接字(close函數):

epoll實現TCP高并發(fā)服務器的流程:

  • 一、創(chuàng)建套接字(socket函數):
  • 通信域選擇IPV4網絡協(xié)議、套接字類型選擇流式;
	int sock_fd = socket(AF_INET,SOCK_STREAM,0); //通信域選擇IPV4、套接字類型選擇流式
  • 二、填充服務器和客戶機的網絡信息結構體:
  • 1.分別定義服務器網絡信息結構體變量serveraddr和客戶機網絡信息結構體變量clientaddr;
  • 2.分別求出服務器和客戶機的網絡信息結構體變量的內存空間大小,以作備用;
  • 3.網絡信息結構體清0;
  • 4.使用IPV4網絡協(xié)議AF_INET
  • 5.在終端預留服務器端主機的IP地址inet_addr(argv[1]);
  • 6.在終端預留服務器端網絡字節(jié)序的端口號htons(atoi(argv[2]));
	struct sockaddr_in serveraddr; //定義服務器網絡信息結構體變量
	struct sockaddr_in clientaddr;
    socklen_t serveraddr_len = sizeof(serveraddr);//求出服務器結構體變量的內存空間大小
    socklen_t clientaddr_len = sizeof(clientaddr);//求出客戶機結構體變量的內存空間大小

    memset(&serveraddr,0,serveraddr_len); //服務器結構體清零
    memset(&clientaddr,0,clientaddr_len);//客戶機結構體清零

    serveraddr.sin_family = AF_INET;  //使用IPV4網絡協(xié)議
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);  //IP地址
    serveraddr.sin_port = htons(atoi(argv[2]));//網絡字節(jié)序的端口號
  • 三、設置允許端口復用(setsockopt函數):
  • setsockopt函數:
  • 功能:設置套接字屬性;

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

	int setsockopt(int sockfd, int level, int optname,
	const void *optval, socklen_t optlen);	
	/*
	參數:
	
		sockfd:套接字
		level:	選項的級別
	
			套接字API級別		SOL_SOCKET
	
			TCP級別			IPPROTO_TCP
	
			IP級別			IPPROTO_IP
	
		optname:選項的名字
	
			套接字API級別
	
				SO_BROADCAST	是否允許發(fā)送廣播
	
				SO_RCVBUF		接收緩沖區(qū)的大小
	
				SO_SNDBUF		發(fā)送緩沖區(qū)的大小
	
				SO_RCVTIMEO		接收超時時間
					參數使用的是 struct timeval 結構體
					如果超時了 函數調用會立即返回-1
					并將錯誤碼置成 EAGAIN
	
				SO_SNDTIMEO			發(fā)送超時時間
	
				SO_REUSEADDR		端口復用
	
			TCP級別
	
				TCP_NODELAY		使能/禁用Nagle算法
	
			IP級別
	
				IP_ADD_MEMBERSHIP	設置加入多播組
	
		optval:	選項的值
	
			沒有特殊說明時 使用的都是int類型
	
		optlen:optval的大小
	
	返回值:
	
		成功 	0
	
		失敗 	-1 	重置錯誤碼
	*/
  • 特別注意:
  • 使用setsockopt設置允許端口復用時,其在代碼的位置在填充網絡信息結構體和bind之間;
	int reuse = 1;
    if(-1 == (setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))))
    {
        perror("setsockopt error");
        exit(-1);
    }
  • 四、套接字和服務器的網絡信息結構體進行綁定(bind函數):

  • 五、套接字設置成被動監(jiān)聽(listen函數):

  • 六、創(chuàng)建紅黑樹(epoll_create函數):

	#include <sys/epoll.h>
	int epoll_create(int size);
	/*
	功能:
		
		創(chuàng)建epoll/創(chuàng)建epoll實例的描述符
	
	參數:
	
	    size:參數已經被忽略了,只需要填寫大于0的值即可
	
	返回值:

        epoll_create 調用成功時會返回一個非負整數epfd,
    
        表示新創(chuàng)建的 epoll 實例的文件描述符,
    
        如果調用失敗則返回 -1,并設置 errno 變量以指示具體錯誤原因
     */
	int epfd = epoll_create(1);
    if(-1 == epfd)
    {
        perror("epoll_create error");
        exit(-1);

    }
  • 七、定義事件結構體變量和存放就緒事件描述符的數組:
  • 事件結構體epoll_event用于描述一個文件描述符上的事件;
			typedef union epoll_data {
               void        *ptr;
               int          fd;  
               uint32_t     u32;
               uint64_t     u64;
           } epoll_data_t;   
           struct epoll_event {
               uint32_t     events;      //EPOLLIN 讀 / EPOLLOUT 寫
               epoll_data_t data;        //存放用戶的數據
           };    

    struct epoll_event event;
    struct epoll_event events[N];
  • 八、將關心的文件描述符加入到紅黑樹(epoll_ctl函數):
  • 功能:epoll的控制操作或者用于向 epoll 實例中添加、修改、刪除事件;
  • epoll_ctl函數:
	int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
	/*
	參數:
	         epfd:epoll的文件描述符
	
	         op:控制方式
	
	            EPOLL_CTL_ADD:添加
	
	            EPOLL_CTL_MOD:修改
	
	            EPOLL_CTL_DEL:刪除
	
	         fd:被操作的文件描述符
	
	         event:(事件)結構體指針
	          
	
	返回值:    
				成功返回0,
	
	            失敗返回-1 置位錯誤碼
	 */
	//添加要檢測事件的描述符
    event.events = EPOLLIN;

    event.data.fd = sock_fd;

    //將關心的文件描述符加入到紅黑樹
    if(-1 == (epoll_ctl(epfd,EPOLL_CTL_ADD,sock_fd,&event)))
    {
        perror("epoll_ctl error");
        exit(-1);

    }
  • 九、等待文件描述符中的事件是否就緒,成功則返回就緒的文件描述符的個數(epoll_wait函數):
  • epoll_wait函數:
	int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
	/*
	參數:

		    epfd:epoll的文件描述符
		
		    events:準備好的事件的結構體地址
		
		    maxevents:返回的最大的文件描述符的個數
		
		    timeout:超時
		
		        >0 :毫秒級別的超時時間
		
		        =0 :立即返回
		
		        =-1:不關心超時時間
	返回值:
	
		     成功返回準備好的文件描述符的個數
		
		     返回0代表超時時間到了
		
		     失敗返回-1置位錯誤碼
	*/
		if(-1 == (ret = epoll_wait(epfd,events,N,-1)))
        {
            perror("epoll_wait error");
            exit(-1);
        }	
  • 十、遍歷就緒的文件描述符集,判斷哪些文件描述符已經準備就緒:
		for(int i = 0; i < ret; ++i)
        {
        	...
        }
  • 十一、找到實際就緒的事件的文件描述符,并且接收來自客戶端的數據(recv函數)和給客戶端發(fā)送應答消息(send函數):
			if(events[i].data.fd == sock_fd)
            {
                //獲取連接成功后新的客戶端
                new_fd = accept(sock_fd,(struct sockaddr *)&clientaddr,&clientaddr_len);
                if(-1 == new_fd)
                {
                    perror("accept error");
                    exit(-1);
                }
                printf("文件描述符[%d]客戶端[%s:%d]連接到了服務器\n",new_fd,inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
                //添加要檢測的文件描述符
                event.events = EPOLLIN;
                event.data.fd = new_fd;
                if(-1 == (epoll_ctl(epfd,EPOLL_CTL_ADD,new_fd,&event)))
                {
                    perror("epoll_ctl error");
                    exit(-1);

                }
                printf("文件描述符[%d]成功掛載在紅黑樹上\n",new_fd);
            }
            else
            {
                memset(buf,0,sizeof(buf));
                int old_fd = events[i].data.fd;
                if(-1 == (nbytes = recv(old_fd,buf,sizeof(buf),0)))
                {
                    perror("recv error");
                    exit(-1);
                }
                else if(0 == nbytes)
                {
                    printf("文件描述符[%d]客戶端斷開了服務器\n",old_fd);

                    //關閉對應的文件描述符
                    close(old_fd);
                    //剔除掛在樹上對應的文件描述符
                    epoll_ctl(epfd,EPOLL_CTL_DEL,old_fd,&event);

                }
                if(!strncmp(buf,"quit",4))
                {
                    printf("文件描述符[%d]客戶端退出了服務器\n",old_fd);
                    //關閉對應的文件描述符
                    close(old_fd);
                    //剔除掛在樹上對應的文件描述符
                    epoll_ctl(epfd,EPOLL_CTL_DEL,old_fd,&event);
                }
                printf("文件描述符[%d]客戶端發(fā)來數據[%s]\n",old_fd,buf);

                //組裝應答消息
                strcat(buf,"-----k");

                //給客戶端發(fā)送應答消息
                send(old_fd,buf,sizeof(buf),0); 
  • 十二、關閉套接字(close函數):

select、poll、epoll三者的區(qū)別:

TCP高并發(fā)服務器簡介(select、poll、epoll實現與區(qū)別),C/S架構學習系列,編程基礎,tcp/ip,服務器,php文章來源地址http://www.zghlxwxcb.cn/news/detail-804858.html

到了這里,關于TCP高并發(fā)服務器簡介(select、poll、epoll實現與區(qū)別)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Linux網絡編程:多路I/O轉接服務器(select poll epoll)

    Linux網絡編程:多路I/O轉接服務器(select poll epoll)

    文章目錄: 一:select 1.基礎API? select函數 思路分析 select優(yōu)缺點 2.server.c 3.client.c 二:poll 1.基礎API? poll函數? poll優(yōu)缺點 read函數返回值 突破1024 文件描述符限制 2.server.c 3.client.c 三:epoll 1.基礎API epoll_create創(chuàng)建? ?epoll_ctl操作? epoll_wait阻塞 epoll實現多路IO轉接思路 epoll優(yōu)缺點

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

    服務器端 客戶端 poll客戶端

    2024年02月12日
    瀏覽(31)
  • C/S架構學習之使用epoll實現TCP特大型并發(fā)服務器

    epoll實現TCP特大型并發(fā)服務器的流程: 一、創(chuàng)建套接字(socket函數): 通信域 選擇 IPV4 網絡協(xié)議、套接字類型選擇 流式 ; 二、填充服務器和客戶機的網絡信息結構體: 1.分別定義服務器網絡信息結構體變量 serveraddr 和客戶機網絡信息結構體變量 clientaddr ; 2.分別求出服務

    2024年02月08日
    瀏覽(26)
  • 使用select實現TCP并發(fā)服務器模型

    使用select實現TCP并發(fā)服務器模型

    本期主要分享的是對于select的使用,使用select實現TCP并發(fā)服務器模型,由于之前所用到的技術知識只能夠支撐我們進行單個訪問,但是有了select之后呢,我們就能夠實現多用戶進行訪問;這也是非常符合客觀需求的; 這次呢我們重點來使用一下select; 用到的頭文件如下: 我

    2024年02月08日
    瀏覽(21)
  • TCP服務器的演變過程:使用epoll構建reactor網絡模型實現百萬級并發(fā)(詳細代碼)

    TCP服務器的演變過程:使用epoll構建reactor網絡模型實現百萬級并發(fā)(詳細代碼)

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

    2024年02月01日
    瀏覽(30)
  • 多路IO—POll函數,epoll服務器開發(fā)流程

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

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

    2024年02月06日
    瀏覽(18)
  • 【Linux網絡編程】TCP并發(fā)服務器的實現(IO多路復用select)

    【Linux網絡編程】TCP并發(fā)服務器的實現(IO多路復用select)

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

    2024年02月03日
    瀏覽(100)
  • 【TCP/IP】利用I/O復用技術實現并發(fā)服務器 - select函數

    【TCP/IP】利用I/O復用技術實現并發(fā)服務器 - select函數

    目錄 I/O復用技術 select函數 設置文件描述符 指定監(jiān)視范圍 設置超時 I/O復用服務器端的實現 ?????? 由服務器創(chuàng)建多個進程來實現并發(fā)的做法有時會帶來一些問題,比如:內存上的開銷、CPU的大量占用等,這些因素會消耗掉服務器端有限的計算資源、進而影響程序之間的執(zhí)

    2024年02月08日
    瀏覽(21)
  • epoll實現并發(fā)服務器

    epoll 是Linux操作系統(tǒng)提供的一種事件通知機制,用于高效處理大量文件描述符上的事件。它是一種基于內核的I/O事件通知接口,可以用于實現高性能的并發(fā)服務器和異步I/O操作。 與傳統(tǒng)的事件通知機制(如 select 和 poll )相比, epoll 具有更高的性能和擴展性。它采用了一種基

    2024年02月09日
    瀏覽(29)
  • epoll并發(fā)服務器的實現

    epoll并發(fā)服務器的實現

    1.實現并發(fā)通信的三種方式 ? 實現并發(fā)通信主要有三種方式: 多進程服務器 、 多路復用服務器 (I/O復用)、 多線程服務器 多進程服務器 ? 多進程服務器指的是利用不同進程處理來自不同客戶端發(fā)來的連接請求,進程之間以輪轉的方式運行,由于各個進程之間輪轉運行的時

    2024年02月03日
    瀏覽(29)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領取紅包

二維碼2

領紅包