Linux high performance:http请求的读取和分析

来源:互联网 发布:ai软件mac破解版 编辑:程序博客网 时间:2024/05/29 11:50
#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <fcntl.h>#define BUFFER_SIZE 4096enum CHECK_STATE { CHECK_STATE_REQUESTLINE = 0, CHECK_STATE_HEADER, CHECK_STATE_CONTENT };enum LINE_STATUS { LINE_OK = 0, LINE_BAD, LINE_OPEN };enum HTTP_CODE { NO_REQUEST, GET_REQUEST, BAD_REQUEST, FORBIDDEN_REQUEST, INTERNAL_ERROR, CLOSED_CONNECTION };static const char* szret[] = { "I get a correct result\n", "Something wrong\n" };LINE_STATUS parse_line( char* buffer, int& checked_index, int& read_index ){    char temp;    for ( ; checked_index < read_index; ++checked_index )    {        temp = buffer[ checked_index ];        if ( temp == '\r' )        {            if ( ( checked_index + 1 ) == read_index )            {                return LINE_OPEN;            }            else if ( buffer[ checked_index + 1 ] == '\n' )            {                buffer[ checked_index++ ] = '\0';                buffer[ checked_index++ ] = '\0';                return LINE_OK;            }            return LINE_BAD;        }        else if( temp == '\n' )        {            if( ( checked_index > 1 ) &&  buffer[ checked_index - 1 ] == '\r' )            {                buffer[ checked_index-1 ] = '\0';                buffer[ checked_index++ ] = '\0';                return LINE_OK;            }            return LINE_BAD;        }    }    return LINE_OPEN;}HTTP_CODE parse_requestline( char* szTemp, CHECK_STATE& checkstate ){    char* szURL = strpbrk( szTemp, " \t" );    if ( ! szURL )    {        return BAD_REQUEST;    }    *szURL++ = '\0';    char* szMethod = szTemp;    if ( strcasecmp( szMethod, "GET" ) == 0 )    {        printf( "The request method is GET\n" );    }    else    {        return BAD_REQUEST;    }    szURL += strspn( szURL, " \t" );    char* szVersion = strpbrk( szURL, " \t" );    if ( ! szVersion )    {        return BAD_REQUEST;    }    *szVersion++ = '\0';    szVersion += strspn( szVersion, " \t" );    if ( strcasecmp( szVersion, "HTTP/1.1" ) != 0 )    {        return BAD_REQUEST;    }    if ( strncasecmp( szURL, "http://", 7 ) == 0 )    {        szURL += 7;        szURL = strchr( szURL, '/' );    }    if ( ! szURL || szURL[ 0 ] != '/' )    {        return BAD_REQUEST;    }    //URLDecode( szURL );    printf( "The request URL is: %s\n", szURL );    checkstate = CHECK_STATE_HEADER;    return NO_REQUEST;}HTTP_CODE parse_headers( char* szTemp ){    if ( szTemp[ 0 ] == '\0' )    {        return GET_REQUEST;    }    else if ( strncasecmp( szTemp, "Host:", 5 ) == 0 )    {        szTemp += 5;        szTemp += strspn( szTemp, " \t" );        printf( "the request host is: %s\n", szTemp );    }    else    {        printf( "I can not handle this header\n" );    }    return NO_REQUEST;}HTTP_CODE parse_content( char* buffer, int& checked_index, CHECK_STATE& checkstate, int& read_index, int& start_line ){    LINE_STATUS linestatus = LINE_OK;    HTTP_CODE retcode = NO_REQUEST;    while( ( linestatus = <span style="font-size:24px;color:#FF0000;">parse_line</span>( buffer, checked_index, read_index ) ) == LINE_OK )//解析出一行的内容    {        char* szTemp = buffer + start_line;        start_line = checked_index;        switch ( checkstate )        {            case CHECK_STATE_REQUESTLINE:            {                retcode = <span style="font-size:24px;color:#FF0000;">parse_requestline</span>( temp, checkstate );//分析请求行                if ( retcode == BAD_REQUEST )                {                    return BAD_REQUEST;                }                break;            }            case CHECK_STATE_HEADER:            {                retcode = <span style="font-size:24px;color:#FF0000;">parse_headers</span>( temp );//分析头部字段                if ( retcode == BAD_REQUEST )                {                    return BAD_REQUEST;                }                else if ( retcode == GET_REQUEST )                {                    return GET_REQUEST;                }                break;            }            default:            {                return INTERNAL_ERROR;            }        }    }    if( linestatus == LINE_OPEN )    {        return NO_REQUEST;    }    else    {        return BAD_REQUEST;    }}int main( int argc, char* argv[] ){    if( argc <= 2 )    {        printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );        return 1;    }    const char* ip = argv[1];    int port = atoi( argv[2] );        struct sockaddr_in address;    bzero( &address, sizeof( address ) );    address.sin_family = AF_INET;    inet_pton( AF_INET, ip, &address.sin_addr );    address.sin_port = htons( port );        int listenfd = socket( PF_INET, SOCK_STREAM, 0 );    assert( listenfd >= 0 );        int ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );    assert( ret != -1 );        ret = listen( listenfd, 5 );    assert( ret != -1 );        struct sockaddr_in client_address;    socklen_t client_addrlength = sizeof( client_address );    int fd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );    if( fd < 0 )    {        printf( "errno is: %d\n", errno );    }    else    {        char buffer[ BUFFER_SIZE ];        memset( buffer, '\0', BUFFER_SIZE );        int data_read = 0;        int read_index = 0;        int checked_index = 0;        int start_line = 0;        CHECK_STATE checkstate = CHECK_STATE_REQUESTLINE;        while( 1 )        {            data_read = recv( fd, buffer + read_index, BUFFER_SIZE - read_index, 0 );            if ( data_read == -1 )            {                printf( "reading failed\n" );                break;            }            else if ( data_read == 0 )            {                printf( "remote client has closed the connection\n" );                break;            }                read_index += data_read;            //分析目前已经获得的所有客户数据            //buffer表示缓冲区,checked_index表示当前已分析多少字节的客户数据,cheeckstate主状态机的初始状态,read_index表示buffer中已读字节数,start_line表示当前分析到哪一行              HTTP_CODE result = <span style="font-size:24px;color:#FF0000;">parse_content</span>( buffer, checked_index, checkstate, read_index, start_line );            if( result == NO_REQUEST )            {                continue;            }            else if( result == GET_REQUEST )            {                send( fd, szret[0], strlen( szret[0] ), 0 );                break;            }            else            {                send( fd, szret[1], strlen( szret[1] ), 0 );                break;            }        }        close( fd );    }        close( listenfd );    return 0;}</span>


0 0
原创粉丝点击