2014-12-04 133 views
4

我正在嘗試編寫解析HTTP GET請求並檢查「主機」是否爲www.bbc.co.uk的代碼。C獲取字符串中的字符串的一部分

這是我的工作代碼:

char data[] = "GET /news/ HTTP/1.1\nHost: www.bbc.co.uk\nConnection: keep-alive"; 
    unsigned int size = strlen(data); 

    if (size>3 && data[0] == 'G' && data[1] == 'E' && data[2] == 'T'){ //If GET Request 
     int host_index = -1; 

     for (int i=4; i<size-4; i++){ 
      if (data[i] == 'H' && data[i+1] == 'o' && data[i+2] == 's' && data[i+3] == 't' 
        && data[i+4] == ':' && data[i+5] == ' '){ 
       host_index = i+6; 
      } 
     } 

     if (host_index != -1 && size > host_index+11 && 
       data[host_index] == 'w' && data[host_index+1] == 'w' && data[host_index+2] == 'w' && 
       data[host_index+3] == '.' && data[host_index+4] == 'b' && data[host_index+5] == 'b' && 
       data[host_index+6] == 'c' && data[host_index+7] == '.' && data[host_index+8] == 'c' && 
       data[host_index+9] == 'o' && data[host_index+10] == '.' && data[host_index+11] == 'u' && 
       data[host_index+12] == 'k') 
     { 
      printf("BBC WEBSITE!\n"); 
     } 

    } 

我覺得這是不是很多很多的代碼。我怎樣才能使這個代碼更緊湊?

[請隨時給普通C.任何第三方庫]

非常感謝!

+0

這取決於你想成爲如何迂腐,這個細節完全是在帖子中丟失。需要多少字符串以預期的格式?如果你不在乎,只要做'if strstr(data,「www.bbc.co.uk」))printf(「BBC WEBSITE!\ n」);' – chux 2014-12-04 21:02:32

回答

2

你的代碼可以更簡潔的寫成:

if (!strncmp(data, "GET ", 4) && strstr(data, "\nHost: www.bbc.co.uk\n")) 
     printf("BBC WEBSITE!\n"); 

不過,雖然這可能工作的99.9%的時間,它不冒號後處理任意空白。正則表達式會有所幫助,但這需要一個第三方庫,這是您不可能擁有的。

一種解決方案是:

if (!strncmp(data, "GET ", 4)) { 
     const char *p = data; 
     char buf[99 + 1]; 
     buf[0] = 0; 
     while ((p = strchr(p, '\n')) && sscanf(++p, "Host: %99s", buf) != 1) 
      ; 
     if (!strcmp(buf, "www.bbc.co.uk")) 
      printf("BBC WEBSITE!\n"); 
    } 

編輯:將上述溶液允許"Host:"後的任何數目的CR和/或LF類。我不清楚HTTP/1.1 LWS(線性空白空間)是否允許這樣做。如果不是,並允許零個或多個空格和製表符,改變sscanf閱讀:

(sscanf(++p, "Host:%*[ \t]%99[^ \t]", buf) == 1 || 
    sscanf(p, "Host:%99[^ \t]",  buf) == 1) 

正如你可以看到,它開始變得混亂。

4

爲什麼不使用strstr()?

拆分大串入使用的strstr(),然後塊由單獨的程序

1
char data[] = "GET /news/ HTTP/1.1\nHost: www.bbc.co.uk\nConnection: keep-alive"; 
unsigned int size = strlen(data); 
char buff[size]; 
sscanf(data, "%*[^:]:%s", buff); 
if(strcmp(buff, "www.bbc.co.uk")==0) 
    puts("BBC"); 
+0

也許'if(sscanf(data,「%* [^\ n]主持人:%s「,buff)== 1)'...'? – chux 2014-12-04 19:40:38

+0

@chux它由需要。 – BLUEPIXY 2014-12-04 19:59:25

+0

你可以解釋一下sscanf部分或註釋就行 – 2014-12-04 20:45:34

2

只使用標準庫函數解析更小的塊,你可以這樣做:

char data[] = 
    "GET /news/ HTTP/1.1\n" 
    "Host: www.bbc.co.uk\n" 
    "Connection: keep-alive"; 

char *found_host = strstr(data, "Host: "); 

if (found_host != NULL) { 
    found_host += sizeof("Host: ") - 1; 

    char *end_of_host = strpbrk(found_host, "\r\n"); 

    if (end_of_host != NULL) { 
     int equal = strncmp(found_host, "www.bbc.co.uk", end_of_host - found_host); 
    } 
} 

注意這並不考慮冒號和值之間的任意數量的空白。