zoukankan      html  css  js  c++  java
  • epoll(1)

    #include<stdio.h>
    #include<fcntl.h>
    #include<unistd.h>
    #include<sys/epoll.h>
    #include<arpa/inet.h>
    #include<sys/socket.h>
    #include<errno.h>
    #include <netinet/tcp.h>
    #include <pthread.h>
    #include<string.h>
    #include<stdlib.h>
    #define MAX 500
    int main(int argc,char* argv[])
    {
        if(argc<2){return -1;}
    
        int port=atoi(argv[1]);
        int sockfd=socket(AF_INET,SOCK_STREAM,0);
        if(sockfd<0){return -1;}
    
        struct sockaddr_in addr;
        memset(&addr,0,sizeof(struct sockaddr_in));
        addr.sin_family=AF_INET;
        addr.sin_port=htons(port);
        addr.sin_addr.s_addr=INADDR_ANY;
    
        if(bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in))<0)
        {
            printf("绑定端口失败!
    ");
            return -1;
        }
        if(listen(sockfd,5)<0)
        {
            return -1;
        }
    
        int epfd=epoll_create(1);
    
        struct epoll_event ev,events[MAX]={0};
        ev.events=EPOLLIN;
        ev.data.fd=sockfd;
        epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&ev);
    
        while(1)
        {
            int nready=epoll_wait(epfd,events,500,-1);
            for(int i=0;i<nready;i++)
            {
                if(events[i].events&EPOLLIN)
                {
                        if(events[i].data.fd==sockfd)
                        {
                            struct sockaddr_in client_addr;
                            memset(&client_addr,0,sizeof(struct sockaddr_in));
                            socklen_t client_len=sizeof(client_addr);
                            int clientfd=accept(sockfd,(struct sockaddr*)&client_addr,&client_len);
                            char str[12];
                            printf("recv from %s at port %d
    ", inet_ntop(AF_INET, &client_addr.sin_addr, str, sizeof(str)),
                            ntohs(client_addr.sin_port));
    
                            ev.events=EPOLLIN|EPOLLET;
                            ev.data.fd=clientfd;
                            epoll_ctl(epfd,EPOLL_CTL_ADD,clientfd,&ev);
                        }
                        else
                        {
                            char buf[1024]={0};
                            int clientfd=events[i].data.fd;
                            int n=recv(clientfd,buf,sizeof(buf),0);
                            //非阻塞情况下,当缓冲区没有数据的时候,会返回-1
                            if(n<0)
                            {
                                if(errno==EAGAIN||errno==EWOULDBLOCK)//其他情况的异常,errno会有相应的标志,这是正常情况下的错误
                                {
                                    continue;
                                }
                                close(clientfd);
                                ev.events=EPOLLIN;
                                ev.data.fd=clientfd;
                                epoll_ctl(epfd,EPOLL_CTL_DEL,clientfd,&ev);
    
                            }else if(n==0)  //客户端与服务器端断开的时候
                            {
    
    /*高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。
    这个场景下会出现大量socket处于TIME_WAIT状态。如果客户端的并发量持续
    很高,此时部分客户端就会显示连接不上。
    比如取一个web页面,1秒钟的http短连接处理完业务,在关闭连接之后,
    这个业务用过的端口会停留在TIMEWAIT状态几分钟,而这几分钟,
    其他HTTP请求来临的时候是无法占用此端口的(占着茅坑不拉翔)。
    单用这个业务计算服务器的利用率会发现,服务器干正经事的时间
    和端口(资源)被挂着无法被使用的时间的比例是 1:几百,服务器资源严重浪费。*/
    
                                printf("服务器与客户端断开连接
    ");
                                //如果这里写了大量业务代码之后忘记关闭了clientfd,那么服务器端就会有大量close_wait状态
                                close(clientfd);
                                ev.events=EPOLLIN;
                                ev.data.fd=clientfd;
                                epoll_ctl(epfd,EPOLL_CTL_DEL,clientfd,&ev);
                            }
                            else 
                            {
                                printf("接收到的数据为:%s,总共%d个字节
    ",buf,n);
                            }
                            
                        }
                        
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    ElasticSearch第三步-中文分词
    centos 6.7 搭建tornado + nginx + supervisor的方法(已经实践)
    python ConfigParser 模块
    collections 模块(namedtuple, deque, Counter )
    Kali 开机报错解决方案
    debian 或者kali 安装git
    kali python pip3 的安装和卸载
    Kali 使用ssh,安装vmware tools 和字体重叠
    装饰器
    python2.7 报错(UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128))
  • 原文地址:https://www.cnblogs.com/SunShine-gzw/p/14704660.html
Copyright © 2011-2022 走看看