⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server_epoll.c

📁 Linux epoll socket server
💻 C
字号:
/*********************************************************
author: Adam Huang
date:2005-10-26
*********************************************************/
#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>
#include <signal.h>

typedef unsigned int UINT32;

#include "packet.h"

#define MAX_FDS 20480
#define MAX_EVENTS 20480

#define LISTENQ 4096
#define SERV_PORT 5555
#define INFTIM 1000

/////////////////Used for report traffic 
UINT32	total_bytes =0;
UINT32	total_packets =0;

UINT32  in_bytes = 0;
UINT32  in_packets = 0;

UINT32  out_bytes = 0;
UINT32  out_packets = 0;

UINT32  moment_conns  = 0;

int     report_interval = 5;
UINT32  times = 1;

void   traffic_report(int none)
{
    fprintf(stderr,"%-10d  %-12d  %-13d  %-15d  %-10d  %-12d  %-11d  %d\n",
                         report_interval * times,
                         moment_conns,
                         total_bytes/report_interval,
                         total_packets/report_interval,
                         in_bytes/report_interval,
                         in_packets/report_interval,
                         out_bytes/report_interval,
                         out_packets/report_interval);
    total_bytes = 0;
    total_packets = 0;
    in_bytes = 0;
    in_packets = 0;
    out_bytes = 0;
    out_packets = 0;
    times ++;

    if(moment_conns < 0)
         moment_conns = 0;

    signal(SIGALRM,traffic_report);
    alarm(report_interval);
} 


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;
     ssize_t n;
     char line[MAXLINE];
     socklen_t clilen;
     //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
     struct epoll_event ev,events[MAX_EVENTS];

     if(argc != 3){
          printf("usage:%s [port] [report_interval]\n",argv[0]);
	  exit(-1);
     }

     report_interval = atoi(argv[2]);
     if(report_interval <= 0)
         report_interval = 5;
     system("echo \"Testting Start time:\"`date +%y-%m-%d/%H:%M:%S`");
     fprintf(stderr,"Port:%d\n",atoi(argv[1]));
     fprintf(stderr,"Report interval:%ds\n",report_interval);
     signal(SIGALRM,traffic_report);
     alarm(report_interval);
     fprintf(stderr,"%-10s  %-10s  %-10s  %-10s  %-10s  %-10s  %-10s  %s\n",
                    "xthScends",
                    "moment_conns",
                    "total_bytes/s",
                    "total_packets/s",
                    "in_bytes/s",
                    "in_packets/s",
                    "out_bytes/s",
                    "out_packets/s");

     //生成用于处理accept的epoll专用的文件描述符
     epfd=epoll_create(MAX_FDS);

     struct sockaddr_in clientaddr;
     struct sockaddr_in serveraddr;
     listenfd = socket(AF_INET, SOCK_STREAM, 0);
     //把socket设置为非阻塞方式
     setnonblocking(listenfd);
     //设置与要处理的事件相关的文件描述符
     ev.data.fd=listenfd;
     //设置要处理的事件类型
     ev.events=EPOLLIN|EPOLLET;
     //注册epoll事件
     epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
 
     bzero(&serveraddr, sizeof(serveraddr));
     serveraddr.sin_family = AF_INET;
     serveraddr.sin_addr.s_addr = htons(INADDR_ANY);

     //serveraddr.sin_port=htons(SERV_PORT);
     serveraddr.sin_port=htons(atoi(argv[1]));
     bind(listenfd,(struct sockaddr *)&serveraddr, sizeof(serveraddr));
     listen(listenfd, LISTENQ);

     maxi = 0; 
     for ( ; ; ) {
          //等待epoll事件的发生
          nfds=epoll_wait(epfd,events,MAX_EVENTS,-1);
          //处理所发生的所有事件      
          for(i=0;i<nfds;++i)
          {
               memset(line,'\0',sizeof(line));
               if(events[i].data.fd==listenfd)
               {
 
                    connfd = accept(listenfd,(struct sockaddr *)&clientaddr, &clilen);
                    if(connfd<0){
                         perror("connfd<0");
                         continue;
                         //exit(1);
                    }
                    setnonblocking(connfd);

                    moment_conns  ++ ;
                    char *str = inet_ntoa(clientaddr.sin_addr);
                    //printf("connect from %s;fd:%d\n",str,connfd);
                    //设置用于读操作的文件描述符
                    ev.data.fd=connfd;
                    //设置用于注测的读操作事件
                    ev.events=EPOLLIN|EPOLLET;
                    //注册ev
                    epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
               }
               else if(events[i].events&EPOLLIN)
               {
                    if ( (sockfd = events[i].data.fd) < 0){
                         moment_conns  -- ;
                         continue;
                    }
                    if ( (n = read(sockfd, line, REQUEST_LEN)) <= 0) {
                         moment_conns -- ;
                         //if (errno == ECONNRESET) {
                              close(sockfd);
                              events[i].data.fd = -1;
                         //}
                         continue;
                    }

                    total_bytes = total_bytes + n;
                    total_packets ++;
                    in_bytes = in_bytes + n;
                    in_packets ++;

                    //printf("read %d bytes form sockfd :%d\n",n,sockfd);
                    //设置用于写操作的文件描述符
                    ev.data.fd=sockfd;
                    //设置用于注测的写操作事件
                    ev.events=EPOLLOUT|EPOLLET;
                    //修改sockfd上要处理的事件为EPOLLOUT
                    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
               }
               else if(events[i].events&EPOLLOUT)
               {    
                    sockfd = events[i].data.fd;
                    if ( sockfd  < 0){
                         moment_conns -- ;
                         continue;
                    }
                    memset(line, '\0', sizeof(line));
                    memset(line, 'A' , RESPONSE_LEN);
                    n = write (sockfd, line, RESPONSE_LEN);
                    if (n <= 0){
                        moment_conns -- ;
                        close(sockfd);
                        events[i].data.fd = -1;
                        continue;
                    }
                    total_bytes = total_bytes + n;
                    total_packets ++ ;
                    out_bytes = out_bytes + n;
                    out_packets ++ ;
                    //printf("write %d bytes to fd %d \n",n , sockfd);
                    //设置用于读操作的文件描述符
                    ev.data.fd=sockfd;
                    //设置用于注测的读操作事件
                    ev.events=EPOLLIN|EPOLLET;
                    //修改sockfd上要处理的事件为EPOLIN
                    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
               }
               else{
                    printf("Unknown error! event.data.fd:%d\n",events[i].data.fd);
               }
 
          }
 
     }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -