框架头文件:
/************************
* HTTP Parser framework
* 2010-01-11
************************/
#ifndef __SIMPLE_HTTP_H__
#define __SIMPLE_HTTP_H__
#define GET_REQUEST_SIZE 1024
#define HEADER_SIZE 1024
#define CONTENT_SIZE 1024000
// response header
typedef struct {
char content_type[32];
char content_length[32];
} http_response;
// build a GET request
int httpGET(char * sndbuf,
int buflen,
const char * http_version,
const char * http_useragent,
const char * http_host,
const char * http_uri);
// read a response from a socket
// (no reconnection, so your socket must be healthy)
int httpResponse(int fd,
char * content,
int len,
http_response * response);
#endif
GET请求拼装
const char * HTTP_GET_FORMAT =
"GET %s %s/r/n" /
"User-Agent: %s/r/n" /
"Host: %s/r/n" /
"/r/n";
nt httpGET(char * sndbuf,
int buflen,
const char * http_version,
const char * http_useragent,
const char * http_host,
const char * http_uri)
{
if (sndbuf == NULL || buflen <= 0)
{
return -1;
}
return snprintf(sndbuf, buflen, HTTP_GET_FORMAT, http_uri, http_version, http_useragent, http_host);
}
Response解析 -- header 与 Content 切分部分int httpResponse(int fd, char * content, int len, http_response * response) { char header[HEADER_SIZE] = { 0 }; char c; char line[1024]; int cindex = 0; // analyze status int status = 0; char * contentptr = content; char * headerptr = header; char * content_head = NULL; int readnum = 0; int content_length = 0; int content_rest_length = 0; if (fd < 0 || content == NULL || len <= 0) { return -1; } if ((readnum = read(fd, header, HEADER_SIZE)) > 0) { while ((c = *headerptr) && content_head == NULL) { switch (status) { case 0: // nothing happend if (c == '/r') { status = 1; httpParseLine(line, cindex, response); // a whole line cindex = 0; memset(line, 0, sizeof(line)); } else { line[cindex++] = c; } headerptr ++; break; case 1: // a /r appeared if (c == '/n') { status = 2; headerptr ++; } else { status = 0; } break; case 2: // a /n followed a /r if (c == '/r') { status = 3; headerptr ++; } else { status = 0; } break; case 3: // a /r followed a /r/n pair if (c == '/n') { status = 4; headerptr ++; } else { status = 0; } break; case 4: // head tail content_head = headerptr; content_length = atoi(response->content_length); content_rest_length = content_length - (readnum - (headerptr - header)); contentptr = content; strncpy(content, content_head, readnum - (headerptr - header)); contentptr += readnum - (headerptr - header); while (content_rest_length > 0) { readnum = read(fd, contentptr, content_rest_length); contentptr += readnum; content_rest_length -= readnum; } break; } } } return 0; }
header Parser
// parser item in head static int httpParseLine(const char * line, int len, http_response * response) { char c; int index = 0; int status = 0; if (line == NULL || len == 0 || response == NULL) { return -1; } while (status != 1) { switch (status) { case 0: // nothing happened if (strncmp(line, "Content-Type:", 13) == 0) { status = 2; } else if (strncmp(line, "Content-Length:", 15) == 0) { status = 3; } else { return -1; } break; case 1: // finished break; case 2: strcpy(response->content_type, line + 13); status = 1; break; case 3: strcpy(response->content_length, line + 15); status = 1; break; } } return 0; }