用epoll()實現併發伺服器通訊
阿新 • • 發佈:2022-03-22
伺服器端程式碼
#include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> #include <sys/types.h> #include <sys/epoll.h> int main(){ //建立socket int lfd = socket(PF_INET,SOCK_STREAM,0); struct sockaddr_in saddr; saddr.sin_port = htons(9999); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = INADDR_ANY; //繫結 bind(lfd,(struct sockaddr*)&saddr,sizeof(saddr)); //監聽 listen(lfd,8); //呼叫epoll_creat()建立一個epoll例項 int epfd = epoll_create(100); //將監聽的檔案描述符新增到epoll例項的rbr中 struct epoll_event epev; epev.events = EPOLLIN; epev.data.fd = lfd; epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&epev); struct epoll_event epevs[1024]; while(1){ int ret = epoll_wait(epfd,epevs,1024,-1); if(ret == -1){ perror("epoll_wait"); exit(-1); } // printf("ret = %d\n",ret);//將客戶端中sleep(1)改為usleep(1000)可以看到ret = 2 for(int i = 0; i < ret; i++){ if(epevs[i].data.fd == lfd){ //監聽的檔案描述符,有客戶端連線 struct sockaddr_in caddr; int len = sizeof(caddr); int cfd = accept(lfd,(struct sockaddr*)&caddr,&len); printf("有新客戶端連線,IP : %d,port : %d\n",caddr.sin_addr.s_addr,caddr.sin_port); epev.events = EPOLLIN;//epev.events = EPOLLIN | EPOLLOUT epev.data.fd = cfd; epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&epev); }else{ if(epevs[i].events & EPOLLOUT){//檢測的有寫入資料 continue; } //檢測到有讀資料到達,需要通訊 char buf[1024] = {0}; int len = read(epevs[i].data.fd,buf,sizeof(buf)); if(len == -1){ perror("read"); exit(-1); }else if(len == 0){ printf("client closed..."); close(epevs[i].data.fd); epoll_ctl(epfd,EPOLL_CTL_DEL,epevs[i].data.fd,NULL); }else if(len > 0){ printf("read buf: %s\n",buf); write(epevs[i].data.fd,buf,strlen(buf)+1); } } } } close(lfd); close(epfd); return 0; }
客戶端程式碼
//客戶端 #include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int main(){ //建立套接字 int fd = socket(AF_INET,SOCK_STREAM,0); if(fd == -1){ perror("socket"); exit(-1); } //連線伺服器 struct sockaddr_in saddr; saddr.sin_family = AF_INET; inet_pton(AF_INET,"192.168.245.128",&saddr.sin_addr.s_addr); saddr.sin_port = htons(9999); int ret = connect(fd,(struct sockaddr*)&saddr,sizeof(saddr)); if(ret == -1){ perror("connect"); exit(-1); } //通訊 char recvBuf[1024] = {0}; int i = 0; while(1){ sprintf(recvBuf,"data : %d\n",i++); write(fd,recvBuf,strlen(recvBuf)); int len = read(fd,recvBuf,sizeof(recvBuf)); if(len == -1){ perror("read"); exit(-1); }else if(len > 0){ printf("recv server data : %s\n",recvBuf); }else if(len == 0){ printf("server closed..."); break; } //sleep(1); usleep(1000); } return 0; }
執行效果圖