首页 > C/C++ > 从头编写高性能服务程序10-请求解析

从头编写高性能服务程序10-请求解析

最终的形态基本上在上次的结构中就定型了
当然有些细节需要完善
不过基本上用这个结构来写service已经是OK了
那么现在就是继续细化这个结构.用来写个比较靠近实际的应用

有了链接的管理
接下来就是对通讯协议的实现
由于是从头开始写
所以协议也由我们自己来实现
先是对请求的解析
从客户端telnet传送过来的数据
回行是用/r/n结尾的
所以我们不停的接受数据
然后判断数据的最后是否是/r/n
如果是的话.就把它和以前的数据一起拼接起来
然后调用请求分析来解析指令

在event_handle结构中
我们加入了command数组
用来存放每次传输过来的数据
直至遇到以/r/n结尾的数据.然后拼接起来,输出,再清空这个数组
从头再接受新的指令

由于使用了epoll和非阻塞accept_fd
所以每次接受到的数据是零散的
需要将每次recv的数据连续的拼接到一个变量中
这就是command数组存在的理由
而command_pos用来保存的是每次拼接后数组的实际存放数据的量
也可以认为是最后一个数据所在数组中的位置
便于下次拼接

下载: code.txt
  1. #include <sys/socket.h>
  2. #include <sys/wait.h>
  3. #include <netinet/in.h>
  4. #include <sys/epoll.h>
  5. #include <sys/sendfile.h> 
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <strings.h>
  11. #include <fcntl.h>
  12.  
  13. typedef struct event_handle{
  14.     int fd;
  15.     int ( * handle )( struct event_handle * ev );
  16.     char command[1024];
  17.     int command_pos;
  18. } EV,* EH;
  19. typedef int ( * EVENT_HANDLE )( struct event_handle * ev );
  20.  
  21.  
  22. int create_listen_fd( int port ){
  23.     int listen_fd;
  24.     struct sockaddr_in my_addr;
  25.     if ( ( listen_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ){
  26.         perror( "create socket error" );
  27.         exit( 1 );
  28.     }
  29.     int flag;
  30.     if ( setsockopt( listen_fd, SOL_SOCKET, SO_REUSEADDR
  31.     , ( char * )&flag, sizeof( flag ) ) == -1 ){
  32.         perror( "setsockopt error" );
  33.     }
  34.     int flags = fcntl( listen_fd, F_GETFL, 0 );
  35.     fcntl( listen_fd, F_SETFL, flags|O_NONBLOCK );
  36.     my_addr.sin_family = AF_INET;
  37.     my_addr.sin_port = htons( port );
  38.     my_addr.sin_addr.s_addr = INADDR_ANY;
  39.     bzero( &( my_addr.sin_zero ), 8 );
  40.     if ( bind( listen_fd, ( struct sockaddr * )&my_addr,
  41.     sizeof( struct sockaddr_in ) ) == -1 ) {
  42.         perror( "bind error" );
  43.         exit( 1 );
  44.     }
  45.     if ( listen( listen_fd, 1 ) == -1 ){
  46.         perror( "listen error" );
  47.         exit( 1 );
  48.     }
  49.     return listen_fd;
  50. }
  51.  
  52. int create_accept_fd( int listen_fd ){
  53.     int addr_len = sizeof( struct sockaddr_in );
  54.     struct sockaddr_in remote_addr;
  55.     int accept_fd = accept( listen_fd,
  56.         ( struct sockaddr * )&remote_addr, &addr_len );
  57.     int flags = fcntl( accept_fd, F_GETFL, 0 );
  58.     fcntl( accept_fd, F_SETFL, flags|O_NONBLOCK );
  59.     return accept_fd;
  60. }
  61.  
  62. int fork_process( int process_num ){
  63.     int i;
  64.     int pid=-1;
  65.     for( i = 0; i < process_num; i++ ){
  66.         if( pid != 0 ){
  67.             pid = fork();
  68.         }
  69.     }
  70.     return pid;
  71. }
  72.  
  73. int handle_hook_v2( EH ev ){
  74.     char in_buf[1024];
  75.     memset( in_buf, 0, 1024 );
  76.     int recv_num = recv( ev->fd, &in_buf, 1024, 0 );
  77.     if( recv_num ==0 ){
  78.         printf( "ProcessID:%d, EPOLLIN, fd:%d, closed\n", getpid(), ev->fd );
  79.         printf( "  recved:%s\n", ev->command );
  80.         close( ev->fd );
  81.     }
  82.     else{
  83.         printf( "ProcessID:%d, EPOLLIN, fd:%d, recv_num:%d;recv:", getpid(), ev->fd, recv_num );
  84.         int i;
  85.         for( i = 0; i<recv_num; i++ ){
  86.             printf( "%02x ", in_buf[i] );
  87.         }
  88.         printf( "\n" );
  89.         memcpy( ev->command + ev->command_pos, in_buf, recv_num );
  90.         ev->command_pos += recv_num;
  91.         if( recv_num == 2 && ( !memcmp( &in_buf[recv_num-2], "\r\n", 2 ) ) ){
  92.             printf( "  recved:%s\n", ev->command );
  93.             memset( ev->command, 0, 1024 );
  94.             ev->command_pos = 0;
  95.         }
  96.     }
  97.     return recv_num;
  98. }
  99.  
  100.  
  101.  
  102. int main(){
  103.     int listen_fd = create_listen_fd( 3389 );
  104.     int pid = fork_process( 3 );
  105.     if( pid == 0 ){
  106.         int accept_handles = 0;
  107.         struct epoll_event ev, events[20];
  108.         int epfd = epoll_create( 256 );
  109.         int ev_s = 0;
  110.        
  111.         ev.data.fd = listen_fd;
  112.         ev.events = EPOLLIN|EPOLLET;
  113.         epoll_ctl( epfd, EPOLL_CTL_ADD, listen_fd, &ev );
  114.         struct event_handle ev_handles[256];
  115.         for( ;; ){
  116.             ev_s = epoll_wait( epfd, events, 20, 500 );
  117.             int i = 0;
  118.             for( i = 0; i<ev_s; i++ ){
  119.                 if( events[i].data.fd == listen_fd ){
  120.                     int max_process_accept = 3;
  121.                     if( accept_handles < max_process_accept ){
  122.                         accept_handles++;
  123.                         int accept_fd = create_accept_fd( listen_fd );
  124.                         ev_handles[accept_handles].fd = accept_fd;
  125.                         ev_handles[accept_handles].handle = handle_hook_v2;
  126.                         ev_handles[accept_handles].command_pos = 0;
  127.                         memset( ev_handles[accept_handles].command, 0, 1024 );
  128.                         ev.data.ptr = &ev_handles[accept_handles];
  129.                         ev.events = EPOLLIN|EPOLLET;
  130.                         epoll_ctl( epfd, EPOLL_CTL_ADD, accept_fd, &ev );
  131.                         printf( "ProcessID:%d, EPOLLIN, fd:%d, accept:%d\n", getpid(), listen_fd, accept_fd );
  132.                     }
  133.                 }
  134.                 else if( events[i].events&EPOLLIN ){
  135.                     EVENT_HANDLE current_handle = ( ( EH )( events[i].data.ptr ) )->handle;
  136.                     EH current_event = ( EH )( events[i].data.ptr );
  137.                     if( ( *current_handle )( current_event )  == 0 ){ 
  138.                         accept_handles--;
  139.                     }
  140.                 }
  141.                 else if( events[i].events&EPOLLOUT ){
  142.                     //need add write event process
  143.                 }
  144.             }
  145.         }
  146.     }
  147.     else{
  148.         //manager the process
  149.         int child_process_status;
  150.         wait( &child_process_status );
  151.     }
  152.    
  153.     return 0;
  154. }
分类: C/C++ 标签:
  1. hoterran
    2010年7月4日18:35 | #1

    应该设计一个evbuffer 的adt。协议的解析也应该封装起来~~
    另外recv 返回-1也要处理一下,毕竟会有EINTR、EWOULDBLOCK

  1. 本文目前尚无任何 trackbacks 和 pingbacks.