框架头文件: /************************ * 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; }