zoukankan      html  css  js  c++  java
  • 高性能服务编程:有限状态机解析HTTP请求代码

    相关函数:

    //该函数返回str1中第一个匹配字符串str2的字符数,未找到返回null。
    char *strpbrk(const char *str1, const char *str2)
    /*
    若参数s1 和s2 字符串相同则返回0。s1 长度大于s2 长度则返回大于0 的值,s1 长度若小于s2 长度则返回小于0 的值。
    */
    
    int strcasecmp (const char *s1, const char *s2);
    /*
    返回字符串 str 开头连续包含字符串 accept 内的字符数目。所以,如果 str 所包含的字符都属于 accept,那么返回 str 的长度;如果 str 的第一个字符不属于 accept,那么返回 0。
    */
    
    size_t strspn(const char *str, const char * accept);
    //该函数返回在字符串 str 中第一次出现字符 c 的位置,如果未找到该字符则返回 NULL。
    
    char *strchr(const char *str, int c)
      1 #include <sys/socket.h>
      2 #include <netinet/in.h>
      3 #include <arpa/inet.h>
      4 #include <assert.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <unistd.h>
      8 #include <errno.h>
      9 #include <string.h>
     10 #include <fcntl.h>
     11 
     12 #define BUFFER_SIZE 4096
     13 enum CHECK_STATE { CHECK_STATE_REQUESTLINE = 0, CHECK_STATE_HEADER, CHECK_STATE_CONTENT };
     14 enum LINE_STATUS { LINE_OK = 0, LINE_BAD, LINE_OPEN };
     15 enum HTTP_CODE { NO_REQUEST, GET_REQUEST, BAD_REQUEST, FORBIDDEN_REQUEST, INTERNAL_ERROR, CLOSED_CONNECTION };
     16 static const char* szret[] = { "I get a correct result
    ", "Something wrong
    " };
     17 
     18 LINE_STATUS parse_line( char* buffer, int& checked_index, int& read_index )
     19 {
     20     char temp;
     21     for ( ; checked_index < read_index; ++checked_index )
     22     {
     23         temp = buffer[ checked_index ];
     24         if ( temp == '
    ' )
     25         {
     26             if ( ( checked_index + 1 ) == read_index )
     27             {
     28                 return LINE_OPEN;
     29             }
     30             else if ( buffer[ checked_index + 1 ] == '
    ' )
     31             {
     32                 buffer[ checked_index++ ] = '';
     33                 buffer[ checked_index++ ] = '';
     34                 return LINE_OK;
     35             }
     36             return LINE_BAD;
     37         }
     38         else if( temp == '
    ' )
     39         {
     40             if( ( checked_index > 1 ) &&  buffer[ checked_index - 1 ] == '
    ' )
     41             {
     42                 buffer[ checked_index-1 ] = '';
     43                 buffer[ checked_index++ ] = '';
     44                 return LINE_OK;
     45             }
     46             return LINE_BAD;
     47         }
     48     }
     49     return LINE_OPEN;
     50 }
     51 
     52 HTTP_CODE parse_requestline( char* szTemp, CHECK_STATE& checkstate )
     53 {
     54     char* szURL = strpbrk( szTemp, " 	" );
     55     if ( ! szURL )
     56     {
     57         return BAD_REQUEST;
     58     }
     59     *szURL++ = '';
     60 
     61     char* szMethod = szTemp;
     62     if ( strcasecmp( szMethod, "GET" ) == 0 )
     63     {
     64         printf( "The request method is GET
    " );
     65     }
     66     else
     67     {
     68         return BAD_REQUEST;
     69     }
     70 
     71     szURL += strspn( szURL, " 	" );
     72     char* szVersion = strpbrk( szURL, " 	" );
     73     if ( ! szVersion )
     74     {
     75         return BAD_REQUEST;
     76     }
     77     *szVersion++ = '';
     78     szVersion += strspn( szVersion, " 	" );
     79     if ( strcasecmp( szVersion, "HTTP/1.1" ) != 0 )
     80     {
     81         return BAD_REQUEST;
     82     }
     83 
     84     if ( strncasecmp( szURL, "http://", 7 ) == 0 )
     85     {
     86         szURL += 7;
     87         szURL = strchr( szURL, '/' );
     88     }
     89 
     90     if ( ! szURL || szURL[ 0 ] != '/' )
     91     {
     92         return BAD_REQUEST;
     93     }
     94 
     95     //URLDecode( szURL );
     96     printf( "The request URL is: %s
    ", szURL );
     97     checkstate = CHECK_STATE_HEADER;
     98     return NO_REQUEST;
     99 }
    100 
    101 HTTP_CODE parse_headers( char* szTemp )
    102 {
    103     if ( szTemp[ 0 ] == '' )
    104     {
    105         return GET_REQUEST;
    106     }
    107     else if ( strncasecmp( szTemp, "Host:", 5 ) == 0 )
    108     {
    109         szTemp += 5;
    110         szTemp += strspn( szTemp, " 	" );
    111         printf( "the request host is: %s
    ", szTemp );
    112     }
    113     else
    114     {
    115         printf( "I can not handle this header
    " );
    116     }
    117 
    118     return NO_REQUEST;
    119 }
    120 
    121 HTTP_CODE parse_content( char* buffer, int& checked_index, CHECK_STATE& checkstate, int& read_index, int& start_line )
    122 {
    123     LINE_STATUS linestatus = LINE_OK;
    124     HTTP_CODE retcode = NO_REQUEST;
    125     while( ( linestatus = parse_line( buffer, checked_index, read_index ) ) == LINE_OK )
    126     {
    127         char* szTemp = buffer + start_line;
    128         start_line = checked_index;
    129         switch ( checkstate )
    130         {
    131             case CHECK_STATE_REQUESTLINE:
    132             {
    133                 retcode = parse_requestline( szTemp, checkstate );
    134                 if ( retcode == BAD_REQUEST )
    135                 {
    136                     return BAD_REQUEST;
    137                 }
    138                 break;
    139             }
    140             case CHECK_STATE_HEADER:
    141             {
    142                 retcode = parse_headers( szTemp );
    143                 if ( retcode == BAD_REQUEST )
    144                 {
    145                     return BAD_REQUEST;
    146                 }
    147                 else if ( retcode == GET_REQUEST )
    148                 {
    149                     return GET_REQUEST;
    150                 }
    151                 break;
    152             }
    153             default:
    154             {
    155                 return INTERNAL_ERROR;
    156             }
    157         }
    158     }
    159     if( linestatus == LINE_OPEN )
    160     {
    161         return NO_REQUEST;
    162     }
    163     else
    164     {
    165         return BAD_REQUEST;
    166     }
    167 }
    168 
    169 int main( int argc, char* argv[] )
    170 {
    171     if( argc <= 2 )
    172     {
    173         printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
    174         return 1;
    175     }
    176     const char* ip = argv[1];
    177     int port = atoi( argv[2] );
    178     
    179     struct sockaddr_in address;
    180     bzero( &address, sizeof( address ) );
    181     address.sin_family = AF_INET;
    182     inet_pton( AF_INET, ip, &address.sin_addr );
    183     address.sin_port = htons( port );
    184     
    185     int listenfd = socket( PF_INET, SOCK_STREAM, 0 );
    186     assert( listenfd >= 0 );
    187     
    188     int ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );
    189     assert( ret != -1 );
    190     
    191     ret = listen( listenfd, 5 );
    192     assert( ret != -1 );
    193     
    194     struct sockaddr_in client_address;
    195     socklen_t client_addrlength = sizeof( client_address );
    196     int fd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
    197     if( fd < 0 )
    198     {
    199         printf( "errno is: %d
    ", errno );
    200     }
    201     else
    202     {
    203         char buffer[ BUFFER_SIZE ];
    204         memset( buffer, '', BUFFER_SIZE );
    205         int data_read = 0;
    206         int read_index = 0;
    207         int checked_index = 0;
    208         int start_line = 0;
    209         CHECK_STATE checkstate = CHECK_STATE_REQUESTLINE;
    210         while( 1 )
    211         {
    212             data_read = recv( fd, buffer + read_index, BUFFER_SIZE - read_index, 0 );
    213             if ( data_read == -1 )
    214             {
    215                 printf( "reading failed
    " );
    216                 break;
    217             }
    218             else if ( data_read == 0 )
    219             {
    220                 printf( "remote client has closed the connection
    " );
    221                 break;
    222             }
    223     
    224             read_index += data_read;
    225             HTTP_CODE result = parse_content( buffer, checked_index, checkstate, read_index, start_line );
    226             if( result == NO_REQUEST )
    227             {
    228                 continue;
    229             }
    230             else if( result == GET_REQUEST )
    231             {
    232                 send( fd, szret[0], strlen( szret[0] ), 0 );
    233                 break;
    234             }
    235             else
    236             {
    237                 send( fd, szret[1], strlen( szret[1] ), 0 );
    238                 break;
    239             }
    240         }
    241         close( fd );
    242     }
    243     
    244     close( listenfd );
    245     return 0;
    246 }
  • 相关阅读:
    01_垂直居中body中的应用
    C++基础知识易错点总结(2)
    辗转相除求最大公约数
    C++基础知识易错点总结(1)
    类对象的建立方式总结
    LeetCode(131)Palindrome Partitioning
    基本套接字编程(7) -- udp篇
    LeetCode(124) Binary Tree Maximum Path Sum
    LeetCode(115) Distinct Subsequences
    LeetCode(97) Interleaving String
  • 原文地址:https://www.cnblogs.com/BillowJ/p/13395119.html
Copyright © 2011-2022 走看看