linux epoll示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/epoll.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <string.h>

#define MAXEVENTS 64

//函数:
//功能:创建和绑定一个TCP socket
//参数:端口
//返回值:创建的socket
static int create_and_bind(char*port)
{
    struct addrinfo hints;
    struct addrinfo *result, *rp;
    int s, sfd;

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;        //return IPv4 and IPV6 choice
    hints.ai_socktype = SOCK_STREAM;    //We want a tcp socket
    hints.ai_flags = AI_PASSIVE;        //All interfaces

    s = getaddrinfo(NULL, port, &hints, &result);
    if(s != 0)
    {
        fprintf(stderr, "getAddrinfo: %s\n", gai_strerror(s));
        return -1;
    }

    for(rp=result; rp != NULL; rp = rp->ai_next)
    {
        sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if(sfd == -1)
            continue;
        s = bind(sfd, rp->ai_addr, rp->ai_addrlen);
        if(s==0)
        {
            break;
        }
        close(sfd);
    }

    if(rp == NULL)
    {
        fprintf(stderr, "Could not bind\n");
        return -1;
    }
    freeaddrinfo(result);
    return sfd;
}

//函数
//功能:设置socket为非阻塞的
static int make_socket_non_blocking(int sfd)
{
    int flags, s;
    //Get file status flag
    flags = fcntl(sfd, F_GETFL, 0);
    if(flags == -1)
    {
        perror("fcntl");
        return -1;
    }
    //Set file status flag
    flags |= O_NONBLOCK;
    s = fcntl(sfd, F_SETFL, flags);
    if(s == -1)
    {
        perror("fcntl");
        return -1;
    }

    return 0;
}
struct  myepoll_data
{
    char    str[20];
    int     sockfd;
};
int main(int argc, char* argv[])
{
    int sfd, s;
    int efd;
    struct epoll_event event;
    struct epoll_event *events;
    if(argc != 2)
    {
        fprintf(stderr, "Usage: %s [port]\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    sfd = create_and_bind(argv[1]);
    if(sfd == -1)
        abort();
    s = make_socket_non_blocking(sfd);
    if(sfd == -1)
        abort();
    s = listen(sfd, SOMAXCONN);
    if(s == -1)
    {
        perror("fcntl");
        return -1;
    }

    efd = epoll_create1(0); 
    if(efd == -1)
    {
        perror("epoll_create");
        abort();
    }

    event.data.fd = sfd;
    event.events = EPOLLIN | EPOLLET;
    s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event);
    if(s == -1)
    {
        perror("epoll_ctl");
        abort();
    }
    events = (struct epoll_event*)calloc(MAXEVENTS, sizeof(event));

    while(1)
    {
        int n, i;
        n = epoll_wait(efd, events, MAXEVENTS, -1);
        for(i=0; i<n; i++)
        {
            if(sfd == events[i].data.fd)
            {
                while(1)
                {
                    struct sockaddr in_addr;
                    socklen_t in_len;
                    int infd;
                    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
                    in_len = sizeof(in_addr);
                    infd = accept(sfd, &in_addr, &in_len);
                    if(infd == -1)
                    {
                        if((errno== EAGAIN)||
                        (errno== EWOULDBLOCK))
                        {
                            /* We have processed all incoming
                            connections.*/
                            break;
                        }
                        else
                        {
                            perror("accept");
                            break;
                        }
                    }
                    s = getnameinfo(&in_addr, in_len,
                                    hbuf,sizeof(hbuf),
                                    sbuf,sizeof(sbuf),
                                    NI_NUMERICHOST| NI_NUMERICSERV);//flag参数:以数字名返回
                    //主机地址和服务地址
                    if(s==0)
                    {
                        printf("Accepted connection on descriptor %d "
                        "(host=%s,port=%s)\n", infd, hbuf,sbuf);
                    }
                    s = make_socket_non_blocking(infd);
                    if(s == -1)
                        abort();
                    event.data.fd = infd;
                    event.events = EPOLLIN | EPOLLET;
                    s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event);//将新的fd添加到epoll的监听队列中
                    if(s == -1)
                    {
                        perror("epoll_ctl");
                        abort();
                    }
                }
                continue;
            }
            else
            {
            /* We have data on the fd waiting to be read. Read and
                    display it. We must read whatever data is available
                    completely,as we are running in edge-triggered mode
                    and won't get a notification again for the same
                    data.*/
                if(EPOLLIN & events[i].events)
                {
                    int done=0;
                
                    while(1)
                    {
                        ssize_t count;
                        char buf[512];
                        count = read(events[i].data.fd, buf, sizeof(buf));
                        if(count == -1)
                        {
                            if(errno != EAGAIN)
                            {
                                perror("read");
                                done = 1;
                            }
                            break;
                        }
                        else if(count == 0)
                        {
                            done = 1;
                            break;
                        }
                        s = write(1, buf, count);
                        if(s == -1)
                        {
                            perror("write");
                            abort();
                        }
                        strcpy(md.str, "12345\n");//自己的数据
                        md.sockfd = events[i].data.fd;
                        event.data.ptr = &md;
                        event.events = EPOLLOUT|EPOLLET;
                        epoll_ctl(efd, EPOLL_CTL_MOD, events[i].data.fd, &event);
                    }
                    if(done)
                    {
                        printf("Closed connection on descriptor %d\n", events[i].data.fd);
                        close(events[i].data.fd);
                    }
                }
                else if(EPOLLOUT & events[i].events)
                {
                    myepoll_data* md = (myepoll_data*)events[i].data.ptr;
                    send(md->sockfd, md->str, strlen(md->str), 0);
                    event.data.fd = md->sockfd;
                    event.events = EPOLLIN|EPOLLET;
                    epoll_ctl(efd, EPOLL_CTL_MOD, md->sockfd, &event);
                }
            }
        }
    }
    free(events);
    close(sfd);


    return EXIT_SUCCESS;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值