通过发送HTTP请求,下载文件
头文件:
1 #ifndef __HTTP__ 2 #define __HTTP__ 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string> 7 #include <winsock.h> 8 9 using namespace std; 10 11 /** 12 * URL相关数据 13 */ 14 typedef struct _URLData { 15 string url; // 完整的url地址 16 string path; // 文件路径 17 string host; // 主机名 18 string ip; // 点分隔的ip 19 int port; // 端口 20 string resName; // 资源名字 21 } URLData; 22 23 /** 24 * 解析url 25 */ 26 void parseURL(string url, URLData* data); 27 28 /** 29 * 链接http服务器 30 */ 31 bool connectHttpServer(int socketId, string ip, int port); 32 33 /** 34 * 生成请求文本 35 */ 36 void generateRequestTxt(URLData* data, string* requestTxt); 37 38 /** 39 * 发送http请求 40 */ 41 bool sendHttpRequest(int socketId, string* requestTxt); 42 43 /** 44 * 接受响应数据 45 */ 46 void recvHttpResponse(int socketId, string* responseTxt); 47 48 /** 49 * 保存http数据 50 */ 51 bool saveHttpData(string* responseTxt, string filePath = "", string fileName = ""); 52 53 /** 54 * 获取http资源 55 */ 56 bool getHttpResource(string url, string filePath = "", string fileName = ""); 57 58 #endif
代码文件:
1 #include "http.h" 2 #include "DNS/DNS.h" 3 #include "time.h" 4 5 /** 6 * 解析url 7 */ 8 void parseURL(string url, URLData* data) 9 { 10 int startPos = 0; 11 string begin = url.substr(0, 4); 12 if (begin == "http") { 13 startPos = 7; 14 } 15 16 int i = startPos; 17 int lastSplitPos = 0; 18 for (int len = url.length(); i<len; i++) { 19 unsigned char ch = url.at(i); 20 21 if (ch == 47) { 22 if (data->host.length() == 0) { 23 data->host = url.substr(startPos, i - startPos); 24 data->path = url.substr(i, url.length() - i); 25 26 break; 27 } 28 29 lastSplitPos = i; 30 } 31 } 32 // data->path = url.substr(iPath, url.length() - iPath); 33 data->url = url; 34 data->port = 80; 35 36 int resNameLastPos = url.length()-1; 37 int resNameFirstPos = 0; 38 for (int i = url.length()-1; i>=0; i--) { 39 unsigned char ch = url.at(i); 40 41 if (ch == '.') 42 resNameLastPos = i; 43 else if (ch == '/') { 44 resNameFirstPos = i + 1; 45 break; 46 } 47 } 48 data->resName = url.substr(resNameFirstPos, resNameLastPos - resNameFirstPos); 49 } 50 51 /** 52 * 链接HTTP服务器 53 */ 54 bool connectHttpServer(int socketId, string ip, int port) 55 { 56 // 初始套接字化地址 57 struct sockaddr_in serverAddr; 58 memset(&serverAddr, 0, sizeof(serverAddr)); 59 serverAddr.sin_family = AF_INET; 60 serverAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); 61 serverAddr.sin_port = htons(port); 62 63 if (connect(socketId, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { 64 return false; 65 } 66 return true; 67 } 68 69 /** 70 * 生成请求文本 71 */ 72 void generateRequestTxt(URLData* data, string* requestTxt) 73 { 74 requestTxt->append("GET "); requestTxt->append(data->path); requestTxt->append(" HTTP/1.1 "); 75 requestTxt->append("Host: "); requestTxt->append(data->host); requestTxt->append(" "); 76 requestTxt->append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 "); 77 requestTxt->append("Accept-Language: zh-CN,zh;q=0.8 "); 78 requestTxt->append("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36 "); 79 requestTxt->append("Accept-Encoding: deflate,sdch "); 80 requestTxt->append("Connection: close "); 81 } 82 83 /** 84 * 发送http请求 85 */ 86 bool sendHttpRequest(int socketId, string* requestTxt) 87 { 88 int sendBytes = send(socketId, requestTxt->c_str(), requestTxt->length(), 0); 89 return sendBytes > 0; 90 } 91 92 /** 93 * 接受响应数据 94 */ 95 void recvHttpResponse(int socketId, string* responseTxt) 96 { 97 char buff[1024]; 98 99 int recvBytes = 0; 100 while ((recvBytes = recv(socketId, buff, 1024, 0)) > 0) { 101 responseTxt->append(buff, recvBytes); 102 } 103 } 104 105 /** 106 * 保存http数据 107 */ 108 bool saveHttpData(string* responseTxt, string filePath, string fileName) 109 { 110 if (fileName == "") { 111 char _fileName[100]; 112 sprintf(_fileName, "%lld", time(0)); 113 fileName = _fileName; 114 } 115 116 string fileExt = "."; 117 118 int i = 0, len = 0; 119 for (i = 0, len = responseTxt->length(); i<len; i++) { 120 unsigned char ch = responseTxt->at(i); 121 122 if (ch == 'C') { 123 unsigned char metaKey[13], typeMetaKey[13] = "Content-Type"; 124 memset(metaKey, 0, 13); 125 memcpy(metaKey, responseTxt->c_str() + i, 12); 126 127 string metaValue; 128 if ( strcmp((char*)metaKey, (char*)typeMetaKey) == 0 ) { 129 for (int j = i+13;;j++) { 130 unsigned char ch = responseTxt->at(j); 131 132 metaValue.push_back(ch); 133 if (ch == ' ') { 134 for (int k = 0, len = metaValue.length(); k<len; k++) { 135 if (metaValue.at(k) == '/') { 136 fileExt.append( metaValue.substr(k+1, metaValue.length() - k - 2) ); 137 fileName.append(fileExt); 138 139 break; 140 } 141 } 142 143 break; 144 } 145 } 146 } 147 } 148 149 if (ch == ' ' && 150 responseTxt->at(i+1) == ' ' && 151 responseTxt->at(i+2) == ' ' && 152 responseTxt->at(i+3) == ' ') { 153 i += 4; 154 break; 155 } 156 } 157 158 FILE* fp = fopen((filePath + fileName).c_str(), "wb+"); 159 if (fp) { 160 fwrite(responseTxt->c_str() + i, 1, responseTxt->length() - i, fp); 161 fclose(fp); 162 163 return true; 164 } 165 return false; 166 } 167 168 /** 169 * 获取http资源 170 */ 171 bool getHttpResource(string url, string filePath, string fileName) 172 { 173 printf("------------------------------------- "); 174 175 int socketId = socket(AF_INET, SOCK_STREAM, 0); 176 if (socketId == INVALID_SOCKET) { 177 printf("Create sokcet failed "); 178 179 return false; 180 } 181 182 // 解析url数据 183 URLData data; 184 parseURL(url, &data); 185 186 // 获取DNS信息 187 if (!getIPAddrByDNS(data.host, &data.ip)) { 188 printf("Get ip(%s) from DNS server failed ", data.host.c_str()); 189 190 return false; 191 } 192 193 // 生成请求文本 194 string requestTxt; 195 generateRequestTxt(&data, &requestTxt); 196 197 // 链接服务器 198 if (!connectHttpServer(socketId, data.ip, data.port)) { 199 printf("Connect http server failed, ip:%s ", data.ip.c_str()); 200 201 return false; 202 } 203 204 printf("Send http request: %s ", requestTxt.c_str()); 205 206 // 发送请求 207 if (!sendHttpRequest(socketId, &requestTxt)) { 208 printf("Send http request failed "); 209 210 return false; 211 } 212 213 // 接受响应 214 string responseTxt; 215 recvHttpResponse(socketId, &responseTxt); 216 217 printf("Recive http response: %s ", responseTxt.c_str()); 218 219 // 保存数据 220 if (!saveHttpData(&responseTxt, filePath, (fileName.length() == 0) ? data.resName : fileName)) { 221 printf("Save response data failed "); 222 return false; 223 } 224 225 closesocket(socketId); 226 227 printf("------------------------------------- "); 228 229 return true; 230 }
使用方法:
1 string url = "http://static.youku.com/index/img/master.png"; 2 getHttpResource(url);