黑铁时代
Programing is not only one kind of technology, but also one kind of art.

通过发送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\r\n");
 75     requestTxt->append("Host: "); requestTxt->append(data->host); requestTxt->append("\r\n");
 76     requestTxt->append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"); 
 77     requestTxt->append("Accept-Language: zh-CN,zh;q=0.8\r\n");
 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\r\n");
 79     requestTxt->append("Accept-Encoding: deflate,sdch\r\n");
 80     requestTxt->append("Connection: close\r\n\r\n");
 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 == '\r') {
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 == '\r' && 
150             responseTxt->at(i+1) == '\n' &&
151             responseTxt->at(i+2) == '\r' &&
152             responseTxt->at(i+3) == '\n') {
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("-------------------------------------\n");
174 
175     int socketId = socket(AF_INET, SOCK_STREAM, 0);
176     if (socketId == INVALID_SOCKET) {
177         printf("Create sokcet failed\n");
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\n", 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\n", data.ip.c_str());
200 
201         return false;
202     }
203 
204     printf("Send http request:\n%s\n", requestTxt.c_str());
205 
206     // 发送请求
207     if (!sendHttpRequest(socketId, &requestTxt)) {
208         printf("Send http request failed\n");
209 
210         return false;
211     }
212 
213     // 接受响应
214     string responseTxt;
215     recvHttpResponse(socketId, &responseTxt);
216 
217     printf("Recive http response:\n%s\n", responseTxt.c_str());
218 
219     // 保存数据
220     if (!saveHttpData(&responseTxt, filePath, (fileName.length() == 0) ? data.resName : fileName)) {
221         printf("Save response data failed\n");
222         return false;
223     }
224 
225     closesocket(socketId);
226 
227     printf("-------------------------------------\n");
228 
229     return true;
230 }

使用方法:

1 string url = "http://static.youku.com/index/img/master.png";
2 getHttpResource(url);

 

posted on 2014-12-17 14:42  黑铁时代  阅读(323)  评论(0编辑  收藏  举报