M5HttpDown.cpp
上传用户:pmma55
上传日期:2020-12-28
资源大小:17k
文件大小:9k
源码类别:

手机WAP编程

开发平台:

Visual C++

  1. #include "M5HttpDown.h"
  2. #include <string.h>
  3. CM5HttpDown::CM5HttpDown()
  4. {
  5.     m_sock = (SOCKET)(NULL) ; 
  6.     m_running = false ;
  7.     m_is_first_resp = true ; 
  8.     m_web_addr = NULL ; 
  9.     m_web_fname = NULL ; 
  10.     m_custom_callback = NULL ; 
  11.     m_custom_data = NULL ; 
  12.     m_total_bytes = 0 ; 
  13.     m_recv_bytes = 0 ; 
  14.     m_recv_buf = new char [HTTP_RECV_BUF_LEN] ;
  15.     memset(m_recv_buf, 0, HTTP_RECV_BUF_LEN) ;  
  16. }
  17. CM5HttpDown::~CM5HttpDown() 
  18. {
  19.     if(m_recv_buf) delete [] m_recv_buf ; 
  20.     if(m_web_addr) delete [] m_web_addr ; 
  21.     if(m_web_fname) delete [] m_web_fname ; 
  22. }
  23. void CM5HttpDown::recv_thread(void * data)
  24. {
  25.     CM5HttpDown * http_down_ptr = static_cast<CM5HttpDown *>(data) ;
  26.     http_down_ptr->recv_thread_handler() ;  
  27.     _endthread() ;     
  28. }
  29. void CM5HttpDown::recv_thread_handler()
  30. {
  31.     fd_set recv_fd ;
  32.     struct timeval tmv ; 
  33.     int    recv_bytes ; 
  34.     int    jump_length ; 
  35.     
  36.     while(m_running) {
  37.         FD_ZERO(&recv_fd) ; 
  38.         FD_CLR(m_sock, &recv_fd) ; 
  39.         FD_SET(m_sock, &recv_fd) ; 
  40.         tmv.tv_sec = 1 ; 
  41.         tmv.tv_usec = 0 ;
  42.         if(select(m_sock+1, &recv_fd, NULL, NULL, &tmv) < 0) {
  43. #ifdef HTTP_DEBUG_MODE
  44.             printf("select recv failed !n") ; 
  45.             fflush(stdout) ; 
  46. #endif
  47.             return ; 
  48.         }
  49.         
  50.         if(FD_ISSET(m_sock, &recv_fd)) {
  51.             // time to read 
  52.             recv_bytes = 0 ; 
  53.             jump_length = 0 ; 
  54.             memset(m_recv_buf, 0, HTTP_RECV_BUF_LEN) ; 
  55.             recv_bytes = recv(m_sock, m_recv_buf, HTTP_RECV_BUF_LEN, 0) ; 
  56.             if(recv_bytes > 0) {
  57.                 if(m_is_first_resp) {
  58.                     if(parse_webfile_info(m_recv_buf, &m_total_bytes, &jump_length)) {
  59.                         if(m_recv_bytes > 0) m_total_bytes += m_recv_bytes ; 
  60. #ifdef HTTP_DEBUG_MODE
  61.                         printf("file length : %dn", m_total_bytes) ; 
  62. #endif
  63.                         m_recv_bytes += (recv_bytes - jump_length) ;  
  64.                         (*m_custom_callback)(m_recv_buf + jump_length, 
  65.                                              recv_bytes - jump_length, 
  66.                                              m_custom_data) ; 
  67.                     } 
  68.                     m_is_first_resp = false ; 
  69.                     continue ; 
  70.                 } else {
  71.                     // common receive procdure 
  72.                     if((m_recv_bytes + recv_bytes) > m_total_bytes) {
  73.                         recv_bytes = m_total_bytes - m_recv_bytes ; 
  74.                         m_recv_bytes = m_total_bytes ; 
  75.                     } else {
  76.                         m_recv_bytes += recv_bytes ;    
  77.                     }
  78.                     (*m_custom_callback)(m_recv_buf, recv_bytes, m_custom_data) ; 
  79.                 }
  80.             } else if(recv_bytes == 0) {
  81.                 // conn down 
  82. #ifdef HTTP_DEBUG_MODE
  83.                 printf("disconn...n") ; 
  84. #endif
  85.                 m_running = false ; 
  86.             }
  87.         }
  88.     }
  89. }
  90. bool CM5HttpDown::send_req(char * req_str, int req_len) 
  91. {
  92.     fd_set send_fd ; 
  93.     struct timeval tmv ; 
  94.     int    send_bytes ; 
  95.     if(!m_sock || req_len <= 0 || req_str == NULL) return false ; 
  96.     
  97.     FD_ZERO(&send_fd) ; 
  98.     FD_CLR(m_sock, &send_fd) ; 
  99.     FD_SET(m_sock, &send_fd) ; 
  100.     tmv.tv_sec = 1 ; 
  101.     tmv.tv_usec = 0 ;
  102.     if(select(m_sock+1, NULL, &send_fd, NULL, &tmv) < 0) {
  103. #ifdef HTTP_DEBUG_MODE
  104.         printf("select send failed !n") ; 
  105.         fflush(stdout) ; 
  106. #endif
  107.         return false ; 
  108.     }
  109.     
  110.     if(FD_ISSET(m_sock, &send_fd)) {
  111.         send_bytes = send(m_sock, req_str, req_len, 0) ; 
  112.         if(req_len != send_bytes) return false ; 
  113.         return true ; 
  114.     }
  115.     return false  ; 
  116. }
  117. bool CM5HttpDown::parse_uri(char * uri, char * web_addr, 
  118.                             char * web_fname, int * web_port)
  119. {
  120.     char * ptr_a = NULL ;
  121.     char * ptr_b = NULL ;
  122.     
  123.     *web_port = HTTP_WEB_PORT ; 
  124.     if(!uri) return false ;
  125.     // search for http or https prefix 
  126.     ptr_a = uri ;
  127.     if(!strncmp(ptr_a, HTTP_PREFIX, strlen(HTTP_PREFIX))) 
  128.         ptr_a = uri + strlen(HTTP_PREFIX) ; 
  129.     else if(!strncmp(ptr_a, HTTPS_PREFIX, strlen(HTTPS_PREFIX)))  
  130.         ptr_a = uri + strlen(HTTPS_PREFIX) ; 
  131.     // get web_addr without "http://" or "https://" prefix 
  132.     ptr_b = strchr(ptr_a, '/');
  133.     if(ptr_b) {
  134.         memcpy(web_addr, ptr_a, strlen(ptr_a) - strlen(ptr_b));
  135.         if(ptr_b + 1)  {
  136.             // get web file name 
  137.             memcpy(web_fname, ptr_b + 1, strlen(ptr_b) - 1);
  138.             web_fname[strlen(ptr_b) - 1] = '' ;
  139.         }
  140.     } else  memcpy(web_addr, ptr_a, strlen(ptr_a)) ;
  141.     if(ptr_b)  web_addr[strlen(ptr_a) - strlen(ptr_b)] = '' ;
  142.     else  web_addr[strlen(ptr_a)] = '' ;
  143.     // search for uri port number
  144.     ptr_a = strchr(web_addr, ':') ;
  145.     if(ptr_a)  *web_port = atoi(ptr_a + 1);
  146.     else *web_port = HTTP_WEB_PORT ;
  147.     return true ; 
  148. }
  149. bool CM5HttpDown::get_resp_field(char * recv_buf, char * field_name, char * end_flag, char * res) 
  150. {
  151.   char * start_ptr = NULL ; 
  152.   char * end_ptr = NULL ; 
  153.   
  154.   start_ptr = strstr(recv_buf, field_name) ; 
  155.   if(start_ptr == NULL) return false ; 
  156.   
  157.   start_ptr += strlen(field_name) ; 
  158.   end_ptr = strstr(start_ptr, end_flag) ; 
  159.   
  160.   if(end_ptr == NULL) return false ; 
  161.   memcpy(res, start_ptr, end_ptr - start_ptr) ; 
  162.   res[end_ptr - start_ptr] = '' ; 
  163.   return true ; 
  164. }
  165. bool CM5HttpDown::parse_webfile_info(char * recv_buf, int * file_length, int * jump_len)
  166. {
  167.     char   tmp_str[50] ; 
  168.     char * offset_str = NULL ; 
  169.   
  170. #ifdef HTTP_DEBUG_MODE
  171.     printf("%sn", recv_buf) ; 
  172. #endif
  173.     // get file length 
  174.     if(!get_resp_field(recv_buf, HTTP_HDR_FILE_LEN, HTTP_HDR_DIV, tmp_str)) 
  175.         return false ; 
  176.     
  177.     *file_length = atoi(tmp_str) ; 
  178.  
  179.     // get current offset 
  180.     offset_str = strstr(recv_buf, HTTP_HDR_END) ; 
  181.     if(offset_str == NULL) return false ; 
  182.     *jump_len = (int)(offset_str + strlen(HTTP_HDR_END) - recv_buf) ; 
  183.     return true ; 
  184. }
  185. bool CM5HttpDown::init_sock(char * server_name, int server_port) 
  186. {
  187.     struct sockaddr_in sock_in ;
  188.     struct hostent * he ;
  189.     {
  190.         // only worked in dos
  191.         WSADATA wsadata ;
  192.         if (WSAStartup(0x0202, &wsadata) != 0) return false ;
  193.     }
  194.     
  195.     // get server ip address 
  196.     he = gethostbyname(server_name) ;
  197.     if (!he) sock_in.sin_addr.s_addr = inet_addr(server_name) ; 
  198.     else {
  199.         sock_in.sin_addr.s_addr = *(unsigned long *)(he->h_addr_list[0]) ; 
  200. #ifdef HTTP_DEBUG_MODE
  201.         printf("ip : %sn", inet_ntoa(sock_in.sin_addr)) ; 
  202. #endif
  203.     }
  204.     
  205.     sock_in.sin_family = AF_INET;
  206.     sock_in.sin_port = htons(server_port);
  207.     m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ;
  208.     
  209.     if(!connect(m_sock,(struct sockaddr *)(&sock_in), sizeof(sock_in))) {
  210.        HANDLE thread_handle ; 
  211.        m_running = true ; 
  212.        thread_handle = (HANDLE)(_beginthread(CM5HttpDown::recv_thread, 0,(void *)(this))) ; 
  213.        return true ; 
  214.     }
  215.     return false ; 
  216. }
  217. bool CM5HttpDown::close_sock()
  218. {
  219.     if(m_running) {
  220.         m_running = false ; 
  221.         Sleep(1000) ;
  222.         if(m_sock) closesocket(m_sock) ; 
  223.     }
  224.     {
  225.         // only worked in dos
  226.         WSACleanup() ; 
  227.     }
  228.     return true ; 
  229. }
  230. bool CM5HttpDown::http_down(char * uri, 
  231.                             RECV_CALLBACK custom_func, void * custom_data,
  232.                             int recv_bytes)
  233. {
  234.     char buffer[HTTP_SEND_BUF_LEN] ;     
  235.     memset(buffer, 0, HTTP_TEMP_BUF_LEN) ;
  236.     
  237.     if(uri == NULL) return false ;  
  238.     m_recv_bytes = recv_bytes ; 
  239.     m_custom_callback = custom_func ; 
  240.     m_custom_data = custom_data ; 
  241.     
  242.     m_web_addr = new char [HTTP_TEMP_BUF_LEN] ; 
  243.     m_web_fname = new char [HTTP_TEMP_BUF_LEN] ;
  244.      
  245.     memset(m_web_addr, 0, HTTP_TEMP_BUF_LEN) ; 
  246.     memset(m_web_fname, 0, HTTP_TEMP_BUF_LEN) ;
  247.     
  248.     parse_uri(uri, m_web_addr, m_web_fname, &m_web_port) ; 
  249.     if(m_recv_bytes == 0) { 
  250.         snprintf(buffer, HTTP_SEND_BUF_LEN, HTTP_COMMON_GET, 
  251.                  m_web_fname, m_web_addr, m_web_port) ; 
  252.     } else {
  253.         snprintf(buffer, HTTP_SEND_BUF_LEN, HTTP_RESUME_GET, 
  254.                  m_web_fname, m_web_addr, m_web_port, m_recv_bytes) ; 
  255.     }
  256. #ifdef HTTP_DEBUG_MODE
  257.     printf("%sn", buffer) ; 
  258. #endif 
  259.     m_running = true ; 
  260.     if(!init_sock(m_web_addr, m_web_port)) return false ; 
  261.     
  262.     // send the request
  263.     return send_req(buffer, strlen(buffer)) ; 
  264. }
  265. bool CM5HttpDown::http_stop()
  266. {
  267.     return close_sock() ; 
  268. }