epoll+socket实现并发服务器 Linux C(版本一)

来源:互联网 发布:linux 注销登录用户 编辑:程序博客网 时间:2024/05/20 11:26

这个是第一个版本。以后本人会逐渐完善。

#include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#include<unistd.h>#include<fcntl.h>#include<sys/types.h>#include<arpa/inet.h>#include<netinet/in.h>#include<sys/socket.h>#include<sys/epoll.h>#include<sys/wait.h>/***********************************************epoll_socket 实现并发服务器(简易)* 这个只是一个接收数据的例子,还有很多小细节没有处理,比如客户端断开后,从epoll中删除fd(以后的版本再更新)*作者:邱于涵*2017年6月23日21:14:10*QQ:1031893464*********************************************///服务器监听端口#define PORT 12345 //最大连接数#define MAXCLIENT 100//最大事件数  epoll event#define MAXEVENTS 10//处理客户端void do_client(int fd){//数据缓冲    char buff[1024];//接收数据    int ret=recv(fd,buff,1024,0);//检测是否断开    if(ret==0)    {        return;    }    if(ret<0)    {        return;    }//输出接收到的数据的内容    printf("data:%s\n",buff);}int main(){//服务器socket 描述符    int sockfd;//服务器 ,客户端 sockaddr_in    struct sockaddr_in server_addr;    struct sockaddr_in client_addr;//创建服务器socket    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)    {        perror("socket");        exit(1);    }//设置server_addr    server_addr.sin_family=AF_INET;    server_addr.sin_port=htons(PORT);    server_addr.sin_addr.s_addr=INADDR_ANY;//初始化 0    bzero(&(server_addr.sin_zero),8);//绑定    if(bind(sockfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr))==-1)    {        perror("bind");        exit(1);    }    printf("bind success \n");//监听(第二个参数是未完成队列,跟系统的链接数量没有任何关系,相当于设置一个瞬间能够处理的阈值。)    if(listen(sockfd,10)==-1)    {        perror("listen");        exit(1);    }    printf("listen success\n");    size_t sin_size=sizeof(struct sockaddr_in);//一个是用来注册事件,一个是触发事件数组    struct epoll_event ev,events[MAXEVENTS];    int conn_sock,nfds,epollfd;//创建epoll    epollfd =epoll_create(MAXCLIENT);    if(epollfd==-1)    {        perror("epoll_create");        exit(1);    }    printf("epoll_create\n");    ev.events=EPOLLIN;    ev.data.fd=sockfd;//注册事件    if(epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&ev)==-1)    {        perror("epoll_ctrl");        exit(1);    }    printf("epoll_ctl \n");    while(1)    {        printf(" epoll_wait\n");//等待事件触发(触发了的事件都会保存在event事件数组里面,这里会阻塞,直到有事件触发,事件数量在nfds里面)        nfds=epoll_wait(epollfd,events,MAXEVENTS,-1);        if(nfds==-1)        {            perror("epoll_pwait");            exit(1);        }        printf("wait,returns nfds=%d/n",nfds);//循环遍历所有事件 进行处理        for(int n=0;n<nfds;n++)        {//如果是服务器监听描述符触发了事件            if(events[n].data.fd==sockfd)            {//accept一个客户端                conn_sock=accept(sockfd,(struct sockaddr*)&client_addr,&sin_size);                if(conn_sock==-1)                {                    perror("accept");                    exit(1);                }                //设置客户端非阻塞                int opts;                opts=fcntl(conn_sock,F_GETFL);                fcntl(conn_sock,F_SETFL,opts|O_NONBLOCK);                //设置触发事件                ev.events=EPOLLIN|EPOLLET;                ev.data.fd=conn_sock;//注册事件                if(epoll_ctl(epollfd,EPOLL_CTL_ADD,conn_sock,&ev)==-1)                {                    perror("epoll_ctl:conn_sock");                    exit(1);                }            }else{//是客户端触发了事件,就处理客户端                do_client(events[n].data.fd);            }        }    }}



阅读全文
0 0