HTTP.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. #pragma once
  2. #include <string>
  3. #include <algorithm>
  4. #include <vector>
  5. #include <WinSock2.h>
  6. #pragma comment(lib, "ws2_32.lib")
  7. #include "HTTPTypes.h"
  8. #include "DNSMap.h"
  9. #include "IInputFiled.h"
  10. /******************************************************************************
  11. HTTP操作类
  12. 功能:
  13. 实现HTTP的操作
  14. 说明:
  15. 使用之前必须调用Init进行初始化。
  16. 自动管理Cookies的发送和保存。
  17. 如果中文出现乱码,请在调用Get、Post之前调用SetCodePage设置编码。
  18. 如需要封装好的HTTPS、异步HTTP、完成端口TCP等商业源码,请联系作者索取。
  19. 作者:
  20. 佳也 2623168833 jaye8090@qq.com
  21. 时间:
  22. 2013-4-8 到 2014-11-12
  23. ******************************************************************************/
  24. class CHTTP
  25. {
  26. public:
  27. CHTTP(void);
  28. ~CHTTP(void);
  29. /**************************************************************************
  30. 初始化
  31. 返回:
  32. 成功返回0,失败返回错误码。
  33. **************************************************************************/
  34. int Init(void);
  35. //基本接口
  36. public:
  37. /**************************************************************************
  38. HTTP的GET操作
  39. 参数:
  40. strHTML 返回值。获取到的HTML内容。
  41. strURL URL地址
  42. strHeader 指定请求头信息,多个请求头用\r\n分隔。
  43. 若为空串,则使用默认的请求头。
  44. strWait 指定等待字符串,出现此字符串则中途停止接收。
  45. 因为中途没有编码转换,所以不要用中文。
  46. 若为空串,则不中途停止接收。
  47. bNeedHeader 是否需要响应头信息
  48. 返回:
  49. 成功返回0,失败返回错误码。
  50. **************************************************************************/
  51. int Get(string & strHTML, string strURL
  52. , string strHeader = ""
  53. , string strWait = "", bool bNeedHeader = false);
  54. /**************************************************************************
  55. HTTP的POST操作
  56. 参数:
  57. strHTML 返回值。获取到的HTML内容。
  58. strURL URL地址
  59. strPostData POST数据
  60. strHeader 指定请求头信息,多个请求头用\r\n分隔。
  61. 若为空串,则使用默认的请求头。
  62. strWait 指定等待字符串,出现此字符串则中途停止接收。
  63. 因为中途没有编码转换,所以不要用中文。
  64. 若为空串,则不中途停止接收。
  65. bNeedHeader 是否需要响应头信息
  66. 返回:
  67. 成功返回0,失败返回错误码。
  68. **************************************************************************/
  69. int Post(string & strHTML, string strURL, string strPostData
  70. , string strHeader = ""
  71. , string strWait = "", bool bNeedHeader = false);
  72. /**************************************************************************
  73. HTTP的POST操作
  74. 参数:
  75. strHTML 返回值。获取到的HTML内容。
  76. strURL URL地址
  77. strPostData POST数据
  78. strHeader 指定请求头信息,多个请求头用\r\n分隔。
  79. 若为空串,则使用默认的请求头。
  80. strWait 指定等待字符串,出现此字符串则中途停止接收。
  81. 因为中途没有编码转换,所以不要用中文。
  82. 若为空串,则不中途停止接收。
  83. bNeedHeader 是否需要响应头信息
  84. 返回:
  85. 成功返回0,失败返回错误码。
  86. **************************************************************************/
  87. int PostFile(string & strHTML, string strURL, std::vector<CInputFiled*>& inputs
  88. , string strHeader = ""
  89. , string strWait = "", bool bNeedHeader = false);
  90. /**************************************************************************
  91. GET图片数据
  92. 参数:
  93. pchImgData 返回值。图片数据的内存地址。
  94. 此内存数据的有效期,到下次调用Get、Post、GetImg为止。
  95. 对象析构后,此内存将被释放。
  96. nImgSize 返回值。图片数据的大小。
  97. strURL URL地址
  98. strHeader 指定请求头信息,多个请求头用\r\n分隔。
  99. 若为空串,则使用默认的请求头。
  100. 返回:
  101. 成功返回0,失败返回错误码。
  102. **************************************************************************/
  103. int GetImg(char * & pchImgData, int & nImgSize
  104. , string strURL, string strHeader = "");
  105. //高级接口
  106. public:
  107. /**************************************************************************
  108. 设置超时时间
  109. 参数:
  110. nConnTimeout 连接超时,毫秒。
  111. nSendTimeout 发送超时,毫秒。
  112. nRecvTimeout 接收超时,毫秒。
  113. **************************************************************************/
  114. void SetTimeout(int nConnTimeout, int nSendTimeout, int nRecvTimeout);
  115. /**************************************************************************
  116. 恢复上次设置的超时时间
  117. **************************************************************************/
  118. void SetTimeoutBack(void);
  119. /**************************************************************************
  120. 添加一个Cookie项
  121. 说明:
  122. 如果此Cookie项已经存在,则替换掉。
  123. 参数:
  124. strCookie 一个Cookie项,格式如下:
  125. "name=value; path=/; domain=host.com"
  126. path或domain属性可以没有。
  127. 返回:
  128. 成功返回0,失败返回错误码。
  129. **************************************************************************/
  130. int AddCookie(string strCookie);
  131. /**************************************************************************
  132. 获取Cookies字符串
  133. 参数:
  134. bOnlyNameValue 是否只需要Cookie名和值属性,剔除path和domain属性。
  135. 返回:
  136. 当前Cookies字符串,格式为:
  137. bOnlyNameValue为false时:
  138. "name1=value1; path=/; domain=host.com;; name2=value2; path..."
  139. Cookie项的属性之间,用;分隔。Cookie项与项之间,用;;分隔。
  140. bOnlyNameValue为true时:
  141. "name1=value1; name2=value2; name3=value3;..."
  142. Cookie项与项之间,用;分隔。
  143. **************************************************************************/
  144. string GetCookies(bool bOnlyNameValue = false);
  145. /**************************************************************************
  146. 设置Cookies
  147. 参数:
  148. strCookies Cookies字符串,格式为:
  149. "name1=value1; name2=value2;...",或者
  150. "name1=value1; path=/; domain=.com;; name2=value2; ..."
  151. 不带path和domain属性时,Cookie项之间用;分隔。
  152. 带path和domain属性时,Cookie项之间用;;分隔。
  153. 返回:
  154. 成功返回0,失败返回错误码。
  155. **************************************************************************/
  156. int SetCookies(string strCookies);
  157. /**************************************************************************
  158. 设置编码方式
  159. 参数:
  160. uiCodePage 编码方式。
  161. CP_ACP为常用的GB2312编码
  162. CP_UTF8为常用的UTF8编码
  163. **************************************************************************/
  164. void SetCodePage(UINT uiCodePage);
  165. /**************************************************************************
  166. 清除DNS缓存
  167. 返回:
  168. 成功返回0,失败返回错误码。
  169. **************************************************************************/
  170. int ClearDNS(void);
  171. //内部操作
  172. private:
  173. /**************************************************************************
  174. 执行HTTP操作
  175. 返回:
  176. 成功返回0,失败返回错误码。
  177. **************************************************************************/
  178. int _Execute(void);
  179. /**************************************************************************
  180. 获取HTML字符串
  181. 参数:
  182. strHTML 返回值。获取到的HTML字符串。
  183. 返回:
  184. 成功返回0,失败返回错误码。
  185. **************************************************************************/
  186. int _GetHTMLStr(string & strHTML);
  187. /**************************************************************************
  188. 分解URL
  189. 返回:
  190. 成功返回0,失败返回错误码。
  191. **************************************************************************/
  192. int _ParseURL(void);
  193. /**************************************************************************
  194. 连接服务器
  195. 返回:
  196. 成功返回0,失败返回错误码。
  197. **************************************************************************/
  198. int _ConnServer(void);
  199. /**************************************************************************
  200. 发送数据
  201. 返回:
  202. 成功返回0,失败返回错误码。
  203. **************************************************************************/
  204. int _SendData(void);
  205. /**************************************************************************
  206. 接收数据
  207. 返回:
  208. 成功返回0,失败返回错误码。
  209. **************************************************************************/
  210. int _RecvData(void);
  211. /**************************************************************************
  212. 剔除响应数据的头部
  213. 返回:
  214. 成功返回0,失败返回错误码。
  215. **************************************************************************/
  216. int _RejectHeader(void);
  217. /**************************************************************************
  218. 提取响应数据的Cookies
  219. 返回:
  220. 成功返回0,失败返回错误码。
  221. **************************************************************************/
  222. int _GetResponseCookies(void);
  223. /**************************************************************************
  224. 接收响应数据
  225. 返回:
  226. 成功返回0,失败返回错误码。
  227. **************************************************************************/
  228. int _RecvResponseData(void);
  229. /**************************************************************************
  230. 一次一次接收数据
  231. 返回:
  232. 成功返回0,失败返回错误码。
  233. **************************************************************************/
  234. int _RecvEachData(void);
  235. /**************************************************************************
  236. 是否结束接收
  237. 返回:
  238. 结束接收返回true,否则返回false。
  239. **************************************************************************/
  240. bool _IsEndRecv(void);
  241. /**************************************************************************
  242. 获取响应数据正文长度
  243. **************************************************************************/
  244. void _GetBodyLen(void);
  245. /**************************************************************************
  246. 开始访问
  247. 返回:
  248. 成功返回0,失败返回错误码。
  249. **************************************************************************/
  250. int _StartVisit(void);
  251. /**************************************************************************
  252. 开始访问
  253. 返回:
  254. 成功返回0,失败返回错误码。
  255. **************************************************************************/
  256. int _StartVisitFile(void);
  257. /**************************************************************************
  258. 结束访问
  259. 返回:
  260. 成功返回0,失败返回错误码。
  261. **************************************************************************/
  262. int _EndVisit(void);
  263. /**************************************************************************
  264. 把数据转换成字符串
  265. 返回:
  266. 成功返回0,失败返回错误码。
  267. **************************************************************************/
  268. int _TransDataToStr(void);
  269. /**************************************************************************
  270. 把接收到的字符串编码转换
  271. 返回:
  272. 成功返回0,失败返回错误码。
  273. **************************************************************************/
  274. int _EncodeRecvStr(void);
  275. /**************************************************************************
  276. 检测等待字符串是否出现
  277. 返回:
  278. 出现了返回true,否则返回false。
  279. **************************************************************************/
  280. bool _CheckWaitStr(void);
  281. /**************************************************************************
  282. 编码POST数据
  283. 返回:
  284. 成功返回0,失败返回错误码。
  285. **************************************************************************/
  286. int _EncodePostData(void);
  287. /**************************************************************************
  288. 获取IP地址
  289. 参数:
  290. strIP 返回值。IP地址字符串。
  291. 返回:
  292. 成功返回0,失败返回错误码。
  293. **************************************************************************/
  294. int _GetIPStr(wstring & strIP);
  295. /**************************************************************************
  296. 编码转换
  297. 参数:
  298. strTrans 返回值。源字符串、目标字符串。
  299. uiDstCodePage 目标编码
  300. uiSrcCodePage 源编码
  301. 返回:
  302. 成功返回0,失败返回错误码。
  303. **************************************************************************/
  304. int _TransCodePage(string & strTrans
  305. , UINT uiDstCodePage, UINT uiSrcCodePage);
  306. /**************************************************************************
  307. 构造请求头
  308. 返回:
  309. 构造好的请求头。
  310. **************************************************************************/
  311. string _MakeHeader(void);
  312. /**************************************************************************
  313. 截取URL的协议部分
  314. 返回:
  315. 成功返回0,失败返回错误码。
  316. **************************************************************************/
  317. int _CutURLPtl(void);
  318. /**************************************************************************
  319. 截取URL的域名部分
  320. 返回:
  321. 成功返回0,失败返回错误码。
  322. **************************************************************************/
  323. int _CutURLDomain(void);
  324. /**************************************************************************
  325. 处理域名中包含端口号的情况
  326. 返回:
  327. 成功返回0,失败返回错误码。
  328. **************************************************************************/
  329. int _ProcessDomainPort(void);
  330. /**************************************************************************
  331. 截取URL的路径部分
  332. 返回:
  333. 成功返回0,失败返回错误码。
  334. **************************************************************************/
  335. int _CutURLPath(void);
  336. /**************************************************************************
  337. 生成Cookies串
  338. 返回:
  339. 用于HTTP请求的Cookies串
  340. **************************************************************************/
  341. string _MakeCookiesString(void);
  342. /**************************************************************************
  343. 判断这条Cookie是否匹配域名和路径属性
  344. 参数:
  345. sCookie 要判断的Cookie
  346. 返回:
  347. 匹配返回true,不匹配返回false。
  348. **************************************************************************/
  349. bool _IsCookieMatch(HTTP::SCookie const & sCookie);
  350. /**************************************************************************
  351. 截取字符串
  352. 参数:
  353. strSource 源字符串。空格会全部剔除。
  354. strHead 头定位字符串。空串,则代表从源字符串最前面开始截取。
  355. strTail 尾定位字符串。空串,则代表截取到源字符串最后面。
  356. 返回:
  357. 截取的字符串。
  358. **************************************************************************/
  359. string _CutStr(string strSource, string strHead, string strTail);
  360. /**************************************************************************
  361. 定位字符串
  362. 参数:
  363. nPos 返回值。字符串的起始位置。
  364. nLen 返回值。字符串的长度。
  365. strSourceLow 源字符串,全小写。
  366. strHeadLow 头定位字符串,全小写。
  367. strTailLow 尾定位字符串,全小写。
  368. 返回:
  369. 定位成功返回true,定位失败返回false。
  370. **************************************************************************/
  371. bool _PosStr(string::size_type & nPos, string::size_type & nLen,
  372. string strSourceLow, string strHeadLow, string strTailLow);
  373. /**************************************************************************
  374. 判断这条Cookie路径是否匹配
  375. 参数:
  376. strCookiePath 需要判断的Cookie路径
  377. 返回:
  378. 匹配返回true,不匹配返回false。
  379. **************************************************************************/
  380. bool _IsCookiePathMatch(string strCookiePath);
  381. /**************************************************************************
  382. 判断这条Cookie域名是否匹配
  383. 参数:
  384. strCookieDomain 需要判断的Cookie域名
  385. 返回:
  386. 匹配返回true,不匹配返回false。
  387. **************************************************************************/
  388. bool _IsCookieDomainMatch(string strCookieDomain);
  389. /**************************************************************************
  390. 判断这条Cookie路径的后面是否匹配,防止/a与/ab匹配的情况。
  391. 参数:
  392. strCookiePath 需要判断的Cookie路径
  393. 返回:
  394. 匹配返回true,不匹配返回false。
  395. **************************************************************************/
  396. bool _IsCookiePathMatchNext(string strCookiePath);
  397. /**************************************************************************
  398. 字符串替换
  399. 参数:
  400. strReplace 返回值。源字符串、替换后的字符串。
  401. strOld 要替换的字符串
  402. strNew 替换成的字符串
  403. **************************************************************************/
  404. void _ReplaceString(string & strReplace, string strOld, string strNew);
  405. /**************************************************************************
  406. 分解Cookie字符串
  407. 参数:
  408. sCookie 返回值。Cookie结构体。
  409. strCookie Cookie字符串
  410. 返回:
  411. 成功返回0,失败返回错误码。
  412. **************************************************************************/
  413. int _ParseCookieStr(HTTP::SCookie & sCookie, string strCookie);
  414. /**************************************************************************
  415. 添加一个Cookie项
  416. 参数:
  417. sCookie 一个Cookie项
  418. 返回:
  419. 成功返回0,失败返回错误码。
  420. **************************************************************************/
  421. int _AddCookie(HTTP::SCookie const & sCookie);
  422. /**************************************************************************
  423. 查找Cookie项是否已经存在Cookies表中
  424. 参数:
  425. sCookie Cookie项。
  426. 返回:
  427. 存在则返回Cookies表下标,不存在返回-1。
  428. **************************************************************************/
  429. int _FindCookie(HTTP::SCookie const & sCookie);
  430. /**************************************************************************
  431. 分割字符串
  432. 参数:
  433. listStr 返回值。分割后的字符串列表。
  434. strSrc 源字符串
  435. strSplit 分割符
  436. **************************************************************************/
  437. void _SplitStr(vector<string> & listStr, string strSrc, string strSplit);
  438. /**************************************************************************
  439. 小写字符串
  440. 参数:
  441. strLower 返回值。源字符串、转换成小写后的字符串。
  442. **************************************************************************/
  443. void _ToLower(string & strLower);
  444. /**************************************************************************
  445. 启动并创建套接字
  446. 返回:
  447. 成功返回0,失败返回错误码。
  448. **************************************************************************/
  449. int _StartupCreateSocket(void);
  450. /**************************************************************************
  451. 填写地址信息
  452. 参数:
  453. addr 返回值。地址信息。
  454. 返回:
  455. 成功返回0,失败返回错误码。
  456. **************************************************************************/
  457. int _FillAddrInfo(sockaddr_in & addr);
  458. /**************************************************************************
  459. 带超时的连接
  460. 参数:
  461. addr 地址信息
  462. 返回:
  463. 成功返回0,失败返回错误码。
  464. **************************************************************************/
  465. int _ConnWithTimeout(sockaddr_in const & addr);
  466. /**************************************************************************
  467. 使用select实现超时
  468. 返回:
  469. 成功返回0,失败返回错误码。
  470. **************************************************************************/
  471. int _SelectTimeout(void);
  472. /**************************************************************************
  473. 设置套接字的超时
  474. 返回:
  475. 成功返回0,失败返回错误码。
  476. **************************************************************************/
  477. int _SetSocketTimeout(void);
  478. //内部数据
  479. private:
  480. string m_strURL; //URL地址
  481. string m_strHeader; //请求头信息
  482. bool m_bPost; //是否需要POST数据
  483. string m_strPostData; //POST数据
  484. std::vector<CInputFiled*> *m_inputs; //post数据
  485. string m_strWait; //等待字符串
  486. bool m_bNeedHeader; //是否需要响应头信息
  487. UINT m_uiCodePage; //编码方式
  488. string m_strPtl; //协议
  489. string m_strDomain; //域名
  490. string m_strPath; //路径
  491. unsigned short m_nPort; //端口
  492. string::size_type m_nPtlTailPos; //URL协议尾部符号://的位置
  493. string::size_type m_nDomainTailPos; //URL域名尾部符号/的位置
  494. int m_nConnTimeout; //连接超时
  495. int m_nSendTimeout; //发送超时
  496. int m_nRecvTimeout; //接收超时
  497. int m_nConnTimeoutBak; //连接超时,备份
  498. int m_nSendTimeoutBak; //发送超时,备份
  499. int m_nRecvTimeoutBak; //接收超时,备份
  500. vector<HTTP::SCookie> m_listCookies; //Cookies表
  501. char * m_pchRecvData; //接收到的数据指针
  502. int m_nDataSize; //接收到的数据大小
  503. string m_strRecvData; //转换成字符串的数据
  504. int m_nHeaderLen; //响应头长度
  505. int m_nBodyLen; //正文长度
  506. static CDNSMap m_mapDNS; //DNS缓存表
  507. bool m_bStartup; //启动套接字是否成功
  508. SOCKET m_socket; //套接字
  509. };