epoll初步使用2

来源:互联网 发布:上海巨人网络工资原画 编辑:程序博客网 时间:2024/06/05 16:36

上一篇中client用的是 发送->等待->接收 模式,如果把client也改为异步,一个进程发送完所有数据,再在epoll上监听返回的数据,能否成功呢。尝试了一下,程序如下:


client_single.cc

#include <stdio.h>#include <stdlib.h>#include <strings.h>#include <string.h>#include <pthread.h>#include <stdlib.h>#include <sys/epoll.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>#define BUFSIZE 10#define SENDTIME 10000#define MAXEVENTS (SENDTIME+100)pthread_attr_t attr;void setnonblocking(int sock){                   int opts;       opts=fcntl(sock,F_GETFL);    if(opts<0)              {                           perror("fcntl(sock,GETFL)");        exit(1);    }               opts = opts|O_NONBLOCK;    if(fcntl(sock,F_SETFL,opts)<0)    {        perror("fcntl(sock,SETFL,opts)");        exit(1);    }}void worker(){        char *local_addr="127.0.0.1";        int port=9988;        struct epoll_event ev, events[MAXEVENTS];        int epollfd = epoll_create(1024);        if(epollfd == -1){                perror("epoll_create");                exit(0);        }        char buf[BUFSIZE];        for(int i=0; i<SENDTIME; i++){                struct sockaddr_in serveraddr;                int fd = socket(AF_INET, SOCK_STREAM, 0);                if(fd == -1){                        perror("socket");                        exit(0);                }                bzero(&serveraddr, sizeof(serveraddr));                serveraddr.sin_family = AF_INET;                inet_aton(local_addr,&(serveraddr.sin_addr));                serveraddr.sin_port=htons(port);                int ret = connect(fd, (sockaddr*)&serveraddr, sizeof(serveraddr));                if(ret<0){                        perror("connect");                        exit(0);                }                setnonblocking(fd);                int len = snprintf(buf, BUFSIZE, "%d", i);                ret = write(fd, buf, len);//                printf("send %s\n", buf);                if(ret != len){                        printf("write error %s write_len:%d expect_len:%d\n", buf, ret, len);                        perror(NULL);                        exit(0);                }                ev.events = EPOLLIN;                ev.data.fd = fd;                ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);                if(ret == -1){                        perror("epoll_ctl");                        exit(0);                }        }        int recvtime=0;        while(1){                int nfds = epoll_wait(epollfd, events, MAXEVENTS, 100);                if(nfds == -1){                        perror(NULL);                }                for(int i=0; i <nfds; i++){                        if(events[i].events & EPOLLIN){                                int curfd = events[i].data.fd;                                memset(buf, 0, BUFSIZE);                                int n = read(curfd, buf, BUFSIZE);                                recvtime++;                                if(n<=0){                                        close(curfd);                                }                                else{//                                        printf("recv %s\n", buf);                                        close(curfd);                                }                        }                }                if(recvtime==SENDTIME){                        break;                }        }} int costms(timeval *v1, timeval *v2){     if(v2->tv_usec < v1->tv_usec){         v2->tv_sec--;         v2->tv_usec+=1000000;     }     return (v2->tv_sec - v1->tv_sec)*1000+(v2->tv_usec - v1->tv_usec)/1000;}void test(){        worker();}               int main(){        timeval v1,v2;        gettimeofday(&v1,NULL);        test();        gettimeofday(&v2,NULL);        int cost = costms(&v1, &v2);        printf("cost:%dms\n", cost);}                

测试发现,当上一篇中的多线程同步发送客户端为单线程时,速度慢于这里的client_single,符合预期。  但当线程数为10或更多时,发送接收同样总个数的请求,多线程同步的程序速度快于 这里的单进程异步。


而且这里的单进程异步存在一个问题:

因为一个fd发送完数据后,要将其放入epoll监听,等接收到返回数据后再关闭fd。这就导致有大量的fd为打开状态,很容易达到系统最大的fd个数,不能再创建新的fd。


所以我的想法是,对于客户端,适合用多线程的同步模式发送接收数据。仅仅是在单一场景下的想法,欢迎大家讨论。


0 0
原创粉丝点击