Linux网络编程——epoll服务器编写

来源:互联网 发布:福州seo推广 编辑:程序博客网 时间:2024/06/14 01:43

epoll服务器端代码:

#include<stdio.h>#include<sys/epoll.h>#include<sys/socket.h>#include<sys/type.h>#include<netinet/in.h>#include<arpa/inet.h>#include<stdlib.h>#include<string.h>static void usage(const char *proc){    printf("Usage: %s [local_ip] [local_port]\n",proc);}typedef struct fd_buf{    int fd;    char buf[10240];}fd_buf_t,*fd_buf_p;static void *alloc_fd_buf(int fd){    fd_buf_p tmp = (fd_buf_p)malloc(sizeof(fd_buf_t));    if(!tmp){        perror("malloc");        return NULL;    }    tmp->fd = fd;    return tmp;}int startup(const char *_ip, int _port){    int sock = socket(AF_INET,SOCK_STREAM,0);    if(sock < 0){        perror("socket");        exit(2);    }    int opt = 1;    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));    struct sockaddr_in local;    local.sin_family = AF_INET;    local.sin_port = htos(_port);    local.sin_addr.s_addr = inet_addr(_ip);    if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){        perror("bind");        exit(3);    }    if(listen(sock, 10) < 0){        perror("listen");        exit(4);    }    return sock;}int main(int argc,char *argv[]){    if(argc != 3){        usage(argv[0]);        return 1;    }    int listen_sock = startup(argv[1], atoi(argv[2]));    int epollfd = epoll_create(256);    if(epollfd < 0){        perror("epoll_create");        close(listen_sock);        return 5;    }    struct epoll_event ev;    ev.events = EPOLLIN;    ev.data.ptr = alloc_fd_buf(listen_sock);    epoll_ctl(epollfd,EPOLL_CTL_ADD,listen_sock,&ev);    int nums = 0;    struct epoll_event_evs[64];    int timeout = -1;    while(1){        switch((nums = epoll_wait(epollfd,evs,64,timeout))){            case -1:                perror("epoll wait");                break;            case 0:                printf("timeout...!\n");                break;            default:                {                    int i = 0;                    for(; i<nums ;i++){                        fd_buf_p fp = (fd_buf_p)evs[i].data.ptr;                        if(fp->fd == listen_sock &&\                                (evs[i].events & EPOLLIN)){                            struct sockaddr_in client;                            socklen_t len = sizeof(client);                            int new_sock = accept(listen_sock,\                                    (struct sockaddr*)&client,&len);                            if(new_sock < 0){                                perror("accept");                                continue;                            }                            printf("get a new client\n");                            ev.events = EPOLLIN;                            ev.data.ptr = alloc_fd_buf(new_sock);                            epoll_ctl(epollfd, EPOLL_CTL_ADD,\                                    new_sock,&ev);                        }                        else if(fp->fd != listen_sock){                            if(evs[i].events & EPOLLIN){                                ssize_t s = read(fp->fd, fp->buf,\                                        sizeof(fp->buf));                                if(s > 0){                                    fp->buf[s] = 0;                                    printf("client say: %s\n",fp->buf);                                    ev.events = EPOLLOUT;                                    ev.data.ptr = fp;                                    epoll_ctl(epollfd,EPOLL_CTL_MOD,\                                            fp->fd,&ev);                                }else if(s<=0){                                    close(fp->fd);                                    epoll_ctl(epollfd, EPOLL_CTL_DEL,\                                            fp->fd,NULL);                                    free(fp);                                }else{                                }                            }else if(evs[i].events & EPOLLOUT){                                const char *msg = "HTTP/1.0 200 OK\r\n\r\n<html><h1>hello epoll!</h1></html>";                                write(fp->fd, msg ,strlen(msg));                                close(fp->fd);                                epoll_ctl(epollfd,EPOLL_CTL_DEL,\                                        fp->fd,NULL);                                free(fp);                            }else{                            }                        }else{                        }                    }//for                }                break;        }    }    return 0;}

epoll优点:
1. 支持一个进程打开大数目的socket描述符。
2. IO效率不随fd数目增加而线性下降,传统的select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。
3. 使用mmap加速内核与用户空间的消息传递。无论是select,poll还是epoll都需要内核把fd消息通知给用户空间,如何避免不必要的内存拷贝就很重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。

原创粉丝点击