#include "stdio.h"

#include "string.h"
#include "stdlib.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "sys/epoll.h"
#include "fcntl.h"
#include "sys/ioctl.h"
#include "errno.h"
void setnonblocking(int sock)
{
  if(fcntl(sock,F_SETFL,O_NONBLOCK)<0)
   {
     printf("fcntl set error1\n");exit(1);
   }
}
 
int main()
{
  int len,nfds,opts,epfd,listenfd,client,sockfd;
  char buf[10],last[5000];
  struct sockaddr_in server_addr,client_addr;
  struct epoll_event ev,events[20];
  
  listenfd=socket(AF_INET,SOCK_STREAM,0);
  setnonblocking(listenfd); 
  bzero(&server_addr,sizeof(server_addr));
  server_addr.sin_family=AF_INET;
  server_addr.sin_port=htons(7878);
  server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
  setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,1,sizeof(int));
  bind(listenfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
  listen(listenfd,20);
 
  epfd=epoll_create(256);
  ev.data.fd=listenfd;
  ev.events=EPOLLIN|EPOLLET;
  epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);  
 
  int i,maxi=0;
  for(;;)
  {
      nfds=epoll_wait(epfd,events,20,500);
      for(i=0;i<nfds;i++)
       {
          if(events[i].data.fd == listenfd)
           {
               socklen_t client_size=sizeof(client_addr);
                client=accept(listenfd,(struct sockaddr *)&client_addr,&client_size);
                if(client <0)
                 {
                     printf("client accept error\n");exit(1);
                 }
                setnonblocking(client);
                ev.data.fd=client;
                ev.events=EPOLLIN|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_ADD,client,&ev);
           }
          else{
                if(events[i].events == EPOLLIN)
                 {
                      //read data
                     len=0;
                     int n,readsock,read_num;
                     if((readsock=events[i].data.fd)<0) continue;
                     ioctl(readsock,FIONREAD,&read_num);
                     printf("we will get %d char\n",read_num);
                     while(len < read_num)
                     { 
                        if((n=read(readsock,buf,10))<0)
                          {
                            if(errno == ECONNRESET)
                              {
                                 close(readsock);
                                 ev.data.fd=readsock;
                                 ev.events=EPOLLIN|EPOLLET;
                                 epoll_ctl(epfd,EPOLL_CTL_DEL,readsock,&ev);
                                 break;
                              }
                             else if(errno == EAGAIN){
                                 break;
                              }
                       }
                      else if(n == 0)
                       {
                            close(readsock);
                            ev.data.fd=readsock;
                            ev.events=EPOLLIN|EPOLLET;
                            epoll_ctl(epfd,EPOLL_CTL_DEL,readsock,&ev);
                            break;
                       }
                    buf[n]='\0';
                    len=len+n;
                    strcat(last,buf);
                    }
                     ev.data.fd=readsock;
                     ev.events=EPOLLOUT|EPOLLET;
                     epoll_ctl(epfd,EPOLL_CTL_MOD,readsock,&ev);  //change mode from read to write
                 }
                if(events[i].events == EPOLLOUT)
                 {
                                //write data
                      int writesock=events[i].data.fd;
                      write(writesock,last,len);
                      ev.data.fd=writesock;
                      ev.events=EPOLLIN|EPOLLET;
                     epoll_ctl(epfd,EPOLL_CTL_DEL,writesock,&ev);
                     close(writesock);
                     bzero(last,sizeof(last));
                 }
          }
       }
  }
 
}