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

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同一块内存实现的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值