epoll_tcp.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/epoll.h>

static int startup(const char *_ip,int _port)
{
 int sock=socket(AF_INET,SOCK_STREAM,0);
 if(sock<0){
  perror("socket");
  exit(2);
 }

 struct sockaddr_in local;
 local.sin_family=AF_INET;
 local.sin_port=htons(_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,5)<0){
  perror("listen");
  exit(4);
 }
 return sock;
}

static int set_noblock(int sock)
{
 int fl=fcntl(sock,F_GETFL);
 return fcntl(sock,F_SETFL,fl|O_NONBLOCK);
}

static void usage(const char *proc )
{
 printf("usage: %s [ip] [port]\n",proc);
}

int main(int argc,char *argv[])
{
 if(argc!=3){
  usage(argv[0]);
  exit(1);
 }
 int listen_sock=startup(argv[1],atoi(argv[2])); //cteate listen socket

 int epfd=epoll_create(256); // 创建一个epoll句柄,占一个fd值
 if(epfd<0){
  perror("epoll_create");
  exit(5);
 }

 struct epoll_event _ev;
 _ev.events=EPOLLIN;
 _ev.data.fd=listen_sock;

 epoll_ctl(epfd, EPOLL_CTL_ADD, listen_sock, &_ev);

 struct epoll_event _ready_ev[128];
 int  _ready_evs=128;
 int _timeout=-1; //block

 int nums=0;
 int done=0;
 while(!done){
  switch( (nums=epoll_wait(epfd, _ready_ev,\
      _ready_evs, _timeout)) ){
   case 0:
    printf("timeout...\n");
    break;
   case -1:
    perror("epoll_wait");
    break;
   default:
    {
     int i=0;
     for(; i< nums; ++i){
      int _fd=_ready_ev[i].data.fd;
      if(_fd==listen_sock && \
        _ready_ev[i].events & EPOLLIN){
       //get a new link...
       struct sockaddr_in peer;
       socklen_t len=sizeof(peer);
       int new_sock=accept(listen_sock,(struct sockaddr*)&peer, &len);
       if(new_sock > 0){
        printf("client info, socket: %s:%d\n", inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));
        _ev.events=EPOLLIN | EPOLLET;//ET
        _ev.data.fd=new_sock;

        set_noblock(new_sock);

        epoll_ctl(epfd, EPOLL_CTL_ADD,\
          new_sock, &_ev);
       }
      }else{
       if(_ready_ev[i].events & EPOLLIN){
        char buf[102400];
        memset(buf, '\0', sizeof(buf));
        //read/write
        ssize_t _s=recv(_fd, buf,\
          sizeof(buf)-1,0);//while need recv done...

        if( _s > 0){
         printf("client# %s\n",buf);
         _ev.events=EPOLLOUT | EPOLLET;
         _ev.data.fd=_fd;
         epoll_ctl(epfd, EPOLL_CTL_MOD,\
           _fd, &_ev);
        }else if( _s==0 ){
         printf("client close...\n");
         epoll_ctl(epfd,EPOLL_CTL_DEL,\
           _fd, NULL);
         close(_fd);
        }else{
         perror("recv");
        }
       }else if(_ready_ev[i].events &\
         EPOLLOUT){
        const char *msg="HTTP/1.1 200 OK\r\n\r\n<h1>hello world  =_=|| </h1>\r\n";
        send(_fd, msg, strlen(msg),0);
        epoll_ctl(epfd,EPOLL_CTL_DEL,_fd, NULL);
        close(_fd);
       }
      }
     }
    }
    break;
  }
 }
}


wKioL1eeHBexF7wHAAAiVPTXmW0247.png


wKioL1eeHBeAsdbzAABIkTrEe-0504.png