天天看點

使用epoll,完成簡單http消息回顯,并用浏覽器測試

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");

   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);

      }

     }

    }

  }

使用epoll,完成簡單http消息回顯,并用浏覽器測試
使用epoll,完成簡單http消息回顯,并用浏覽器測試
下一篇: dup/dup2

繼續閱讀