zoukankan      html  css  js  c++  java
  • epoll分布式通讯

    参考http://www.xmailserver.org/linux-patches/nio-improve.html  epoll通讯

    参考https://blog.csdn.net/yangquanhui1991/article/details/47446245?locationNum=4&fps=1任务调度算法

    注意: select/poll/epoll的作用是IO复用, 要实现并发, 还是需要交个其他线程/进程去处理。 业界很多成熟的服务组件, 就是这么玩的, 如nginx.

    创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

    eg:

    #include <iostream>
    #include <sys/socket.h>
    #include <sys/epoll.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <errno.h>
    using namespace std;
    #define MAXLINE 5
    #define OPEN_MAX 100
    #define LISTENQ 20
    #define SERV_PORT 5000
    #define INFTIM 1000
    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);
    }
    }
    int main(int argc, char* argv[])
    {
    int i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber;
    ssize_t n;
    char line[MAXLINE];
    socklen_t clilen;
    if ( 2 == argc )
    {
    if( (portnumber = atoi(argv[1])) < 0 )
    {
    fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]);
    return 1;
    }
    }
    else
    {
    fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]);
    return 1;
    }
    struct epoll_event ev,events[20]; //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
    epfd=epoll_create(256); //生成用于处理accept的epoll专用的文件描述符
    struct sockaddr_in clientaddr;
    struct sockaddr_in serveraddr;
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    setnonblocking(listenfd); //把socket设置为非阻塞方式
    ev.data.fd=listenfd; //设置与要处理的事件相关的文件描述符
    ev.events=EPOLLIN|EPOLLET; //设置要处理的事件类型

    epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); //注册epoll事件
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    char *local_addr="127.0.0.1";
    inet_aton(local_addr,&(serveraddr.sin_addr));
    serveraddr.sin_port=htons(portnumber);
    bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
    listen(listenfd, LISTENQ);
    maxi = 0;
    for ( ; ; ) {
    nfds=epoll_wait(epfd,events,20,500); //等待epoll事件的发生
    for(i=0;i<nfds;++i) //处理所发生的所有事件
    {
    if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
    {
    connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);
    if(connfd<0){
    perror("connfd<0");
    exit(1);
    }
    char *str = inet_ntoa(clientaddr.sin_addr);
    cout << "accapt a connection from " << str << endl;
    ev.data.fd=connfd; //设置用于读操作的文件描述符
    ev.events=EPOLLIN|EPOLLET; //设置用于注测的读操作事件
    epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); //注册ev
    }
    else if(events[i].events&EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。
    {
    cout << "EPOLLIN" << endl;
    if ( (sockfd = events[i].data.fd) < 0)
    continue;
    if ( (n = read(sockfd, line, MAXLINE)) < 0) {
    if (errno == ECONNRESET) {
    close(sockfd);
    events[i].data.fd = -1;
    } else
    std::cout<<"readline error"<<std::endl;
    } else if (n == 0) {
    close(sockfd);
    events[i].data.fd = -1;
    }
    line[n] = '/0';
    cout << "read " << line << endl;
    ev.data.fd=sockfd; //设置用于写操作的文件描述符
    ev.events=EPOLLOUT|EPOLLET; //设置用于注测的写操作事件
    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改sockfd上要处理的事件为EPOLLOUT
    }
    else if(events[i].events&EPOLLOUT) // 如果有数据发送
    {
    sockfd = events[i].data.fd;
    write(sockfd, line, n);
    ev.data.fd=sockfd; //设置用于读操作的文件描述符
    ev.events=EPOLLIN|EPOLLET; //设置用于注测的读操作事件
    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改sockfd上要处理的事件为EPOLIN
    }
    }
    }
    return 0;
    }

  • 相关阅读:
    一个改写MBR的例子
    explore没有桌面
    Guidance of Set up FTP Server
    重启远程机器(不登录远程机器下的重启)
    Eclipse 一些小知识
    check time period
    Scrum 冲刺——Day 1
    Scrum 冲刺——Day 2
    初学C语言
    CSS选择器
  • 原文地址:https://www.cnblogs.com/anlg-dongxh/p/9327898.html
Copyright © 2011-2022 走看看