我试图编写解析HTTP GET请求的代码并检查" Host"是www.bbc.co.uk。
这是我的工作代码:
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 :(得分:4)
为什么不使用strstr()?
使用strstr()将大字符串拆分为块,然后通过单独的例程解析较小的块
答案 1 :(得分: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);
}
}
请注意,这不会考虑冒号和值之间的任意数量的空格。
答案 2 :(得分: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)
正如你所看到的,它开始变得混乱。
答案 3 :(得分: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");