linux下HttpGet、HttpPost的C++实现

来源:互联网 发布:如何加入淘宝直播 编辑:程序博客网 时间:2024/05/21 08:45
  1. #include "HttpRequest.h"  
  2.   
  3. int main()  
  4. {  
  5.     HttpRequest* Http = new HttpRequest;  
  6.       
  7.     char* str = (char*)malloc(BUFSIZE);  
  8.       
  9.     memset(str, 0, BUFSIZE);  
  10.     if(Http->HttpGet("http://www.baidu.com", str)) {  
  11.         printf("%s\n", str);  
  12.     } else {  
  13.         printf("http://www.baidu.com HttpGet请求失败!\n");  
  14.     }  
  15.       
  16.     memset(str, 0, BUFSIZE);      
  17.     //安装Tomcat  
  18.     if(Http->HttpGet("127.0.0.1", str)) {  
  19.         printf("%s\n", str);  
  20.     } else {  
  21.         printf("127.0.0.1 HttpGet请求失败!\n");  
  22.     }  
  23.   
  24.     free(str);  
  25.     return 0;  
  26. }  


[cpp] view plain copy
  1. #ifndef __HTTP__  
  2. #define __HTTP__  
  3.   
  4. #include <string.h>  
  5. #include <stdlib.h>  
  6. #include <stdio.h>  
  7. #include <unistd.h>  
  8. #include <fcntl.h>  
  9. #include <errno.h>  
  10. #include <netdb.h>  
  11. #include <stdarg.h>  
  12. #include <sys/socket.h>  
  13. #include <netinet/in.h>  
  14. #include <arpa/inet.h>  
  15. #include <sys/types.h>        
  16. #include <sys/socket.h>  
  17.   
  18. #define BUFSIZE 41000  
  19. #define URLSIZE 1024  
  20. #define INVALID_SOCKET -1  
  21. #define __DEBUG__  
  22.   
  23. class HttpRequest  
  24. {  
  25.     public:  
  26.         HttpRequest();  
  27.         ~HttpRequest();  
  28.         void DebugOut(const char *fmt, ...);  
  29.           
  30.         int HttpGet(const char* strUrl, char* strResponse);  
  31.         int HttpPost(const char* strUrl, const char* strData, char* strResponse);  
  32.   
  33.     private:  
  34.         int   HttpRequestExec(const char* strMethod, const char* strUrl, const char* strData, char* strResponse);  
  35.         char* HttpHeadCreate(const char* strMethod, const char* strUrl, const char* strData);  
  36.         char* HttpDataTransmit(char *strHttpHead, const int iSockFd);  
  37.               
  38.         int   GetPortFromUrl(const char* strUrl);  
  39.         char* GetIPFromUrl(const char* strUrl);  
  40.         char* GetParamFromUrl(const char* strUrl);  
  41.         char* GetHostAddrFromUrl(const char* strUrl);  
  42.           
  43.         int   SocketFdCheck(const int iSockFd);   
  44.           
  45.         static int m_iSocketFd;  
  46. };  
  47.   
  48. #endif  


[cpp] view plain copy
  1. #include "HttpRequest.h"  
  2.   
  3. HttpRequest::HttpRequest()  
  4. {  
  5.       
  6. }  
  7.   
  8. HttpRequest::~HttpRequest()  
  9. {  
  10.       
  11. }  
  12.   
  13.   
  14. /** 
  15. *   功能描述:HttpGet请求 
  16. *   参数说明: 
  17. *               strUrl:     Http请求URL 
  18. *               strResponse:Http请求响应 
  19. *   返 回 值: 
  20. *               1表示成功 
  21. *               0表示失败 
  22. **/  
  23. int HttpRequest::HttpGet(const char* strUrl, char* strResponse)  
  24. {  
  25.     return HttpRequestExec("GET", strUrl, NULL, strResponse);  
  26. }  
  27.   
  28.   
  29. /** 
  30. *   功能描述:HttpPost请求 
  31. *   参数说明: 
  32. *               strUrl:     Http请求URL 
  33. *               strData:    POST请求发送的数据 
  34. *               strResponse:Http请求响应 
  35. *   返 回 值: 
  36. *               1表示成功 
  37. *               0表示失败 
  38. **/  
  39. int HttpRequest::HttpPost(const char* strUrl, const char* strData, char* strResponse)  
  40. {  
  41.     return HttpRequestExec("POST", strUrl, strData, strResponse);  
  42. }  
  43.   
  44.   
  45. //执行HTTP请求,GET或POST  
  46. int HttpRequest::HttpRequestExec(const char* strMethod, const char* strUrl, const char* strData, char* strResponse)  
  47. {  
  48.     //判断URL是否有效  
  49.     if((strUrl == NULL) || (0 == strcmp(strUrl, ""))) {  
  50.         DebugOut("%s %s %d\tURL为空\n", __FILE__, __FUNCTION__, __LINE__);   
  51.         return 0;  
  52.     }  
  53.       
  54.     //限制URL长度  
  55.     if(URLSIZE < strlen(strUrl)) {  
  56.         DebugOut("%s %s %d\tURL的长度不能超过%d\n", __FILE__, __FUNCTION__, __LINE__, URLSIZE);   
  57.         return 0;  
  58.     }  
  59.       
  60.     //创建HTTP协议头  
  61.     char* strHttpHead = HttpHeadCreate(strMethod, strUrl, strData);  
  62.       
  63.     //判断套接字m_iSocketFd是否有效,有效就直接发送数据  
  64.     if(m_iSocketFd != INVALID_SOCKET) {  
  65.         //检查SocketFd是否为可写不可读状态  
  66.         if(SocketFdCheck(m_iSocketFd) > 0) {  
  67.             char* strResult = HttpDataTransmit(strHttpHead, m_iSocketFd);  
  68.             if(NULL != strResult) {  
  69.                 strcpy(strResponse, strResult);  
  70.                 return 1;  
  71.             }  
  72.         }  
  73.     }  
  74.   
  75.     //Create socket  
  76.     m_iSocketFd = INVALID_SOCKET;  
  77.     m_iSocketFd = socket(AF_INET, SOCK_STREAM, 0);   
  78.     if (m_iSocketFd < 0 ) {   
  79.         DebugOut("%s %s %d\tsocket error! Error code: %d,Error message: %s\n", __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));   
  80.         return 0;  
  81.     }  
  82.     
  83.     //Bind address and port  
  84.     int iPort = GetPortFromUrl(strUrl);  
  85.     if(iPort < 0) {  
  86.         DebugOut("%s %s %d\t从URL获取端口失败\n", __FILE__, __FUNCTION__, __LINE__);   
  87.         return 0;  
  88.     }     
  89.     char* strIP = GetIPFromUrl(strUrl);  
  90.     if(strIP == NULL) {  
  91.         DebugOut("%s %s %d\t从URL获取IP地址失败\n", __FILE__, __FUNCTION__, __LINE__);  
  92.         return 0;  
  93.     }  
  94.     struct sockaddr_in servaddr;  
  95.     bzero(&servaddr, sizeof(servaddr));   
  96.     servaddr.sin_family = AF_INET;   
  97.     servaddr.sin_port = htons(iPort);   
  98.     if (inet_pton(AF_INET, strIP, &servaddr.sin_addr) <= 0 ) {   
  99.       DebugOut("%s %s %d\tinet_pton error! Error code: %d,Error message: %s\n", __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));   
  100.       close(m_iSocketFd);  
  101.       m_iSocketFd = INVALID_SOCKET;  
  102.       return 0;   
  103.     }  
  104.       
  105.     //Set non-blocking  
  106.     int flags = fcntl(m_iSocketFd, F_GETFL, 0);  
  107.     if(fcntl(m_iSocketFd, F_SETFL, flags|O_NONBLOCK) == -1) {  
  108.         close(m_iSocketFd);  
  109.         m_iSocketFd = INVALID_SOCKET;  
  110.         DebugOut("%s %s %d\tfcntl error! Error code: %d,Error message: %s\n", __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));   
  111.         return 0;  
  112.     }  
  113.   
  114.     //非阻塞方式连接  
  115.     int iRet = connect(m_iSocketFd, (struct sockaddr *)&servaddr, sizeof(servaddr));  
  116.     if(iRet == 0) {  
  117.         char* strResult = HttpDataTransmit(strHttpHead, m_iSocketFd);  
  118.         if(NULL != strResult) {  
  119.             strcpy(strResponse, strResult);  
  120.             free(strResult);  
  121.             return 1;  
  122.         } else {  
  123.             close(m_iSocketFd);  
  124.             m_iSocketFd = INVALID_SOCKET;  
  125.             free(strResult);  
  126.             return 0;  
  127.         }  
  128.     }  
  129.     else if(iRet < 0) {  
  130.         if(errno != EINPROGRESS) {  
  131.             return 0;  
  132.         }  
  133.     }  
  134.       
  135.     iRet = SocketFdCheck(m_iSocketFd);  
  136.     if(iRet > 0) {  
  137.         char* strResult = HttpDataTransmit(strHttpHead, m_iSocketFd);  
  138.         if(NULL == strResult) {  
  139.             close(m_iSocketFd);  
  140.             m_iSocketFd = INVALID_SOCKET;  
  141.             return 0;  
  142.         }  
  143.         else {  
  144.             strcpy(strResponse, strResult);  
  145.             free(strResult);  
  146.             return 1;  
  147.         }  
  148.     }  
  149.     else {  
  150.         close(m_iSocketFd);  
  151.         m_iSocketFd = INVALID_SOCKET;  
  152.         return 0;  
  153.     }  
  154.       
  155.     return 1;  
  156. }  
  157.   
  158.   
  159. //构建HTTP消息头  
  160. char* HttpRequest::HttpHeadCreate(const char* strMethod, const char* strUrl, const char* strData)  
  161. {  
  162.     char* strHost = GetHostAddrFromUrl(strUrl);  
  163.     char* strParam = GetParamFromUrl(strUrl);  
  164.       
  165.     char* strHttpHead = (char*)malloc(BUFSIZE);  
  166.     memset(strHttpHead, 0, BUFSIZE);  
  167.   
  168.     strcat(strHttpHead, strMethod);   
  169.     strcat(strHttpHead, " /");   
  170.     strcat(strHttpHead, strParam);  
  171.     free(strParam);  
  172.     strcat(strHttpHead, " HTTP/1.1\r\n");  
  173.     strcat(strHttpHead, "Accept: */*\r\n");     
  174.     strcat(strHttpHead, "Accept-Language: cn\r\n");   
  175.     strcat(strHttpHead, "User-Agent: Mozilla/4.0\r\n");  
  176.     strcat(strHttpHead, "Host: ");   
  177.     strcat(strHttpHead, strHost);  
  178.     strcat(strHttpHead, "\r\n");  
  179.     strcat(strHttpHead, "Cache-Control: no-cache\r\n");   
  180.     strcat(strHttpHead, "Connection: Keep-Alive\r\n");  
  181.     if(0 == strcmp(strMethod, "POST"))  
  182.     {  
  183.         char len[8] = {0};  
  184.         unsigned uLen = strlen(strData);  
  185.         sprintf(len, "%d", uLen);         
  186.           
  187.         strcat(strHttpHead, "Content-Type: application/x-www-form-urlencoded\r\n");  
  188.         strcat(strHttpHead, "Content-Length: ");   
  189.         strcat(strHttpHead, len);   
  190.         strcat(strHttpHead, "\r\n\r\n");   
  191.         strcat(strHttpHead, strData);   
  192.     }  
  193.     strcat(strHttpHead, "\r\n\r\n");  
  194.       
  195.     free(strHost);  
  196.       
  197.     return strHttpHead;   
  198. }  
  199.   
  200.   
  201. //发送HTTP请求并接受响应  
  202. char* HttpRequest::HttpDataTransmit(char *strHttpHead, const int iSockFd)  
  203. {  
  204.     char* buf = (char*)malloc(BUFSIZE);  
  205.     memset(buf, 0, BUFSIZE);  
  206.     int ret = send(iSockFd,(void *)strHttpHead,strlen(strHttpHead)+1,0);   
  207.     free(strHttpHead);  
  208.     if (ret < 0) {   
  209.         DebugOut("%s %s %d\tsend error! Error code: %d,Error message: %s\n", __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));   
  210.         close(iSockFd);  
  211.         return NULL;   
  212.     }  
  213.       
  214.     while(1)  
  215.     {  
  216.         ret = recv(iSockFd, (void *)buf, BUFSIZE,0);   
  217.         if (ret == 0) //连接关闭  
  218.         {         
  219.             close(iSockFd);  
  220.             return NULL;   
  221.         }  
  222.         else if(ret > 0) {                         
  223.             return buf;   
  224.         }  
  225.         else if(ret < 0) //出错  
  226.         {   
  227.             if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {  
  228.                 continue;  
  229.             }  
  230.             else {  
  231.                 close(iSockFd);  
  232.                 return NULL;  
  233.             }  
  234.         }  
  235.     }  
  236. }  
  237.   
  238.   
  239. //从HTTP请求URL中获取主机地址,网址或者点分十进制IP地址  
  240. char* HttpRequest::GetHostAddrFromUrl(const char* strUrl)  
  241. {     
  242.     char url[URLSIZE] = {0};  
  243.     strcpy(url, strUrl);  
  244.       
  245.     char* strAddr = strstr(url, "http://");//判断有没有http://  
  246.     if(strAddr == NULL) {  
  247.         strAddr = strstr(url, "https://");//判断有没有https://  
  248.         if(strAddr != NULL) {  
  249.             strAddr += 8;  
  250.         }  
  251.     } else {  
  252.         strAddr += 7;  
  253.     }  
  254.       
  255.     if(strAddr == NULL) {  
  256.         strAddr = url;  
  257.     }  
  258.     int iLen = strlen(strAddr);  
  259.     char* strHostAddr = (char*)malloc(iLen+1);  
  260.     memset(strHostAddr, 0, iLen+1);  
  261.     for(int i=0; i<iLen+1; i++) {  
  262.         if(strAddr[i] == '/') {  
  263.             break;  
  264.         } else {  
  265.             strHostAddr[i] = strAddr[i];  
  266.         }  
  267.     }  
  268.   
  269.     return strHostAddr;  
  270. }  
  271.   
  272.   
  273. //从HTTP请求URL中获取HTTP请参数  
  274. char* HttpRequest::GetParamFromUrl(const char* strUrl)  
  275. {     
  276.     char url[URLSIZE] = {0};  
  277.     strcpy(url, strUrl);  
  278.       
  279.     char* strAddr = strstr(url, "http://");//判断有没有http://  
  280.     if(strAddr == NULL) {  
  281.         strAddr = strstr(url, "https://");//判断有没有https://  
  282.         if(strAddr != NULL) {  
  283.             strAddr += 8;  
  284.         }  
  285.     } else {  
  286.         strAddr += 7;  
  287.     }  
  288.       
  289.     if(strAddr == NULL) {  
  290.         strAddr = url;  
  291.     }  
  292.     int iLen = strlen(strAddr);  
  293.     char* strParam = (char*)malloc(iLen+1);  
  294.     memset(strParam, 0, iLen+1);  
  295.     int iPos = -1;  
  296.     for(int i=0; i<iLen+1; i++) {  
  297.         if(strAddr[i] == '/') {  
  298.             iPos = i;  
  299.             break;  
  300.         }  
  301.     }  
  302.     if(iPos == -1) {  
  303.         strcpy(strParam, "");;  
  304.     } else {  
  305.         strcpy(strParam, strAddr+iPos+1);  
  306.     }  
  307.     return strParam;  
  308. }  
  309.   
  310.   
  311. //从HTTP请求URL中获取端口号  
  312. int HttpRequest::GetPortFromUrl(const char* strUrl)  
  313. {  
  314.     int iPort = -1;  
  315.     char* strHostAddr = GetHostAddrFromUrl(strUrl);   
  316.     if(strHostAddr == NULL) {  
  317.         return -1;  
  318.     }  
  319.       
  320.     char strAddr[URLSIZE] = {0};  
  321.     strcpy(strAddr, strHostAddr);  
  322.     free(strHostAddr);  
  323.       
  324.     char* strPort = strchr(strAddr, ':');  
  325.     if(strPort == NULL) {  
  326.         iPort = 80;  
  327.     } else {  
  328.         iPort = atoi(++strPort);  
  329.     }  
  330.     return iPort;  
  331. }  
  332.   
  333.   
  334. //从HTTP请求URL中获取IP地址  
  335. char* HttpRequest::GetIPFromUrl(const char* strUrl)  
  336. {  
  337.     char* strHostAddr = GetHostAddrFromUrl(strUrl);  
  338.     int iLen = strlen(strHostAddr);  
  339.     char* strAddr = (char*)malloc(iLen+1);  
  340.     memset(strAddr, 0, iLen+1);  
  341.     int iCount = 0;  
  342.     int iFlag = 0;  
  343.     for(int i=0; i<iLen+1; i++) {  
  344.         if(strHostAddr[i] == ':') {  
  345.             break;  
  346.         }  
  347.           
  348.         strAddr[i] = strHostAddr[i];  
  349.         if(strHostAddr[i] == '.') {  
  350.             iCount++;  
  351.             continue;  
  352.         }  
  353.         if(iFlag == 1) {  
  354.             continue;  
  355.         }  
  356.           
  357.         if((strHostAddr[i] >= '0') || (strHostAddr[i] <= '9')) {  
  358.             iFlag = 0;  
  359.         } else {  
  360.             iFlag = 1;  
  361.         }  
  362.     }  
  363.     free(strHostAddr);  
  364.       
  365.     if(strlen(strAddr) <= 1) {  
  366.         return NULL;  
  367.     }  
  368.       
  369.     //判断是否为点分十进制IP地址,否则通过域名地址获取IP地址  
  370.     if((iCount == 3) && (iFlag == 0)) {  
  371.         return strAddr;  
  372.     } else {  
  373.         struct hostent *he = gethostbyname(strAddr);  
  374.         free(strAddr);  
  375.         if (he == NULL) {  
  376.             return NULL;  
  377.         } else {  
  378.             struct in_addr** addr_list = (struct in_addr **)he->h_addr_list;            
  379.             for(int i = 0; addr_list[i] != NULL; i++) {  
  380.                 return inet_ntoa(*addr_list[i]);  
  381.             }  
  382.             return NULL;  
  383.         }  
  384.     }  
  385. }  
  386.   
  387.   
  388. //检查SocketFd是否为可写不可读状态  
  389. int HttpRequest::SocketFdCheck(const int iSockFd)  
  390. {  
  391.     struct timeval timeout ;  
  392.     fd_set rset,wset;  
  393.     FD_ZERO(&rset);  
  394.     FD_ZERO(&wset);  
  395.     FD_SET(iSockFd, &rset);  
  396.     FD_SET(iSockFd, &wset);  
  397.     timeout.tv_sec = 3;  
  398.     timeout.tv_usec = 500;  
  399.     int iRet = select(iSockFd+1, &rset, &wset, NULL, &timeout);  
  400.     if(iRet > 0)  
  401.     {  
  402.         //判断SocketFd是否为可写不可读状态  
  403.         int iW = FD_ISSET(iSockFd,&wset);  
  404.         int iR = FD_ISSET(iSockFd,&rset);  
  405.         if(iW && !iR)  
  406.         {  
  407.             char error[4] = "";  
  408.             socklen_t len = sizeof(error);  
  409.             int ret = getsockopt(iSockFd,SOL_SOCKET,SO_ERROR,error,&len);  
  410.             if(ret == 0)  
  411.             {  
  412.                 if(!strcmp(error, ""))  
  413.                 {  
  414.                     return iRet;//表示已经准备好的描述符数  
  415.                 }  
  416.                 else   
  417.                 {  
  418.                     DebugOut("%s %s %d\tgetsockopt error code:%d,error message:%s", __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));  
  419.                 }  
  420.             }  
  421.             else  
  422.             {  
  423.                 DebugOut("%s %s %d\tgetsockopt failed. error code:%d,error message:%s", __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));  
  424.             }  
  425.         }  
  426.         else  
  427.         {             
  428.             DebugOut("%s %s %d\tsockFd是否在可写字符集中:%d,是否在可读字符集中:%d\t(0表示不在)\n", __FILE__, __FUNCTION__, __LINE__, iW, iR);  
  429.         }  
  430.     }  
  431.     else if(iRet == 0)  
  432.     {  
  433.         return 0;//表示超时  
  434.     }  
  435.     else  
  436.     {  
  437.         return -1;//select出错,所有描述符集清0  
  438.     }  
  439.     return -2;//其他错误  
  440. }  
  441.   
  442.   
  443. //打印输出  
  444. void HttpRequest::DebugOut(const char *fmt, ...)  
  445. {  
  446. #ifdef __DEBUG__  
  447.     va_list ap;  
  448.     va_start(ap, fmt);  
  449.     vprintf(fmt, ap);  
  450.     va_end(ap);  
  451. #endif  
  452. }  
  453.   
  454.   
  455. int HttpRequest::m_iSocketFd = INVALID_SOCKET;