epoll初步使用2

上一篇中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。


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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值