MTK Socket学习——HTTP请求

  当然要理解这个,得知道一个HTTP请求是什么样子的和HTTP协议的交互过程。要详细了解 可以看 RFC 标准文档。简单来说,HTTP 协议是请求应答模式,客户端发一个请求,服务器短发一个答复。客户端说:要xxx网页,服务器就把xxx网页返回给你。交互就需要一个规范,这个就是请求和应答的头,比如 请求的第一行: GET /index.html HTTP/1.1 就表示要获得 index.html。(如果要在命令行下模拟,可以输入 telnet http://www.baidu.com/ 80 , 链接成功后,输入 GET / HTTP/1.1 回车回车,就能获得baidu首页了,这个过程就是模拟了想服务器发送了一个最简单的HTTP 请求)

  简单过程分析如下:

  1 分析URL 把域名,请求地址,和 端口 拆分开

  2 进行域名解析,也就是把网址解析成ip地址,这个是异步的过程

  3等解析完成之后,对这个ip地址进行链接

  4 链接成功,组装HTTP 请求 头,发送数据

  5 如果发送成功,那么一会就会收到通知,有数据可读

  6 收到可读消息后,读取内容。

  7 交互完成,关闭socket

  具体代码分析:

ExpandedBlockStart.gif View Code
int en_soc_demo_http_send_request( void)
  //  是否初始化 
  if (soc_demo_transaction) 
  { 
    //  当前状态, HTTP_DNS_QUERY 表示第一步需要域名解析 
    if (soc_demo_transaction->state == HTTP_DNS_QUERY && (soc_demo_app_http_url_struct*) soc_demo_transaction->url_parsed_info == NULL) 
    { 
      //  解析URL,主要是把域名,请求地址,端口区分出来 
      //  比如  http://blog.csdn.net/yanwuxufeng  域名是  http://blog.csdn.net  
      //  请求地址是yanwuxufeng ,端口默认是 80 
      soc_demo_transaction->url_parsed_info = (soc_demo_app_http_url_struct*) en_soc_demo_http_get_parsed_url( soc_demo_transaction->url, soc_demo_transaction->url_len); 
      if (soc_demo_transaction->url_parsed_info) 
      { 
        //  根据域名,获取域名的ip地址 
        //  这是个异步的过程,回调函数得到结果 
        (void)en_soc_demo_get_host_by_name( HTTP, (kal_uint8*) soc_demo_transaction->url_parsed_info->host_name); 
        return EN_SOC_SUCCESS; 
      } 
      else 
      { 
        en_soc_output_result(EN_SOC_INVAL_PARA, NULL, 0); 
        return EN_SOC_INVAL_PARA; 
      } 
    } 
    //  解析完ip地址,就可以封装HTTP 请求头,然后发送 
    else if 
    (soc_demo_transaction->state == HTTP_TCP_CON_CREATING) 
    { 
      kal_int8 ret; 
      char CRLF[3] = {0x0d, 0x0a, 0x00}; 
      soc_demo_transaction->state = HTTP_TCP_CON_CREATED; 
      /* Create HTTP Get Message */ 
      //  设置HTTP 请求方法 
      soc_demo_transaction->snd_data_len = 0; 
      strcat(soc_demo_transaction->snd_buffer, "GET "); 
      soc_demo_transaction->snd_data_len += 4; 
      //  设置请求 URI 
      if (soc_demo_transaction->url_parsed_info->url_link) 
      { 
        strcat( (char*)soc_demo_transaction->snd_buffer, (char*)soc_demo_transaction->url_parsed_info->url_link); 
        soc_demo_transaction->snd_data_len += soc_demo_transaction->url_parsed_info->url_link_len; 
        strcat((char*)soc_demo_transaction->snd_buffer, " "); 
        soc_demo_transaction->snd_data_len += 2; 
      } 
      else 
      { 
        //  没有就是根目录, 
        strcat((char*)soc_demo_transaction->snd_buffer, "/ "); 
        soc_demo_transaction->snd_data_len += 2; 
      } 
      //  设置协议版本 
      strcat((char*)soc_demo_transaction->snd_buffer, "HTTP/1.1"); 
      soc_demo_transaction->snd_data_len += 8; 
      //  第一行结束,加上 换行符 
      strcat((char*)soc_demo_transaction->snd_buffer, CRLF); 
      soc_demo_transaction->snd_data_len += 2;
      //  设置主机,在cmwap 请求是,这个是必须的 
      strcat((char*)soc_demo_transaction->snd_buffer, "Host: "); 
      soc_demo_transaction->snd_data_len += 6; 
      // 主机域名 
      strcat((char*)soc_demo_transaction->snd_buffer, (char*)soc_demo_transaction->url_parsed_info->host_name); 
      soc_demo_transaction->snd_data_len += soc_demo_transaction->url_parsed_info->host_name_len; 
      strcat((char*)soc_demo_transaction->snd_buffer, CRLF); 
      soc_demo_transaction->snd_data_len += 2; 
      strcat((char*)soc_demo_transaction->snd_buffer, "Connection: Closed"); 
      soc_demo_transaction->snd_data_len += 18; 
      strcat((char*)soc_demo_transaction->snd_buffer, CRLF); 
      soc_demo_transaction->snd_data_len += 2; 
      strcat((char*)soc_demo_transaction->snd_buffer, CRLF); 
      soc_demo_transaction->snd_data_len += 2; 
      soc_demo_transaction->server_ip_addr.port = soc_demo_transaction->url_parsed_info->ser_port_num; 
      //  进行链接 
      ret = soc_connect(soc_demo_transaction->socket_id, &soc_demo_transaction->server_ip_addr); 
      //  链接成功,进行下一步动作 
      if (ret == SOC_SUCCESS) 
      { 
        en_soc_demo_http_send_request(); 
        return EN_SOC_SUCCESS; 
      } 
      //  如果是block,那么进行等待,等到消息的返回 
      else if (ret == SOC_WOULDBLOCK) 
      { 
        mmi_frm_set_protocol_event_handler(MSG_ID_APP_SOC_NOTIFY_IND, (PsIntFuncPtr)em_soc_demo_app_socket_notify, MMI_TRUE); 
        return EN_SOC_SUCCESS; 
      } 
      else 
      { 
        //  错误 
        if (ret == SOC_ERROR) 
        { 
          en_soc_output_result(EN_SOC_PEER_NOT_REACHABLE, NULL, 0); 
          return EN_SOC_PEER_NOT_REACHABLE; 
        } 
        else 
        { 
          en_soc_output_result(EN_SOC_ERROR, NULL, 0); return EN_SOC_ERROR; 
        } 
      } 
    } 
    //  链接成功之后,可以发送数据 
    else if (soc_demo_transaction->state == HTTP_TCP_CON_CREATED || soc_demo_transaction->state == REQ_SEND_RETRY || soc_demo_transaction->state == REQ_SENDING) 
    { 
      kal_int32 ret; 
      //  第一次发送,  
      if (soc_demo_transaction->state != REQ_SENDING) 
      { 
        soc_demo_transaction->snd_counter = 0; 
      } 
      soc_demo_transaction->state = REQ_SENDING; 
      //  发送数据 
      ret = soc_send( soc_demo_transaction->socket_id, (kal_uint8*) (soc_demo_transaction->snd_buffer + soc_demo_transaction->snd_counter), (soc_demo_transaction->snd_data_len - soc_demo_transaction->snd_counter), 0); 
      if (ret > 0) 
      { 
        //  发送完毕 
        //  其实这里有个bug 
        //  应该是 if ((soc_demo_transaction->snd_counter + ret) == (kal_int32) soc_demo_transaction->snd_data_len)    //  因为数据量很小,几乎不问题. 
        if (ret == (kal_int32)  soc_demo_transaction->snd_data_len) 
        { 
          soc_demo_transaction->state = REQ_SENT; 
          soc_demo_transaction->post_retry_counter++; 
          em_soc_demo_app_start_timer(); 
          /* wait for servwer's response */ 
          en_soc_demo_tcp_app_recv_response(); return EN_SOC_SUCCESS; 
        } 
        else 
        { 
          //  发送了一部分,需要继续发送 
          soc_demo_transaction->snd_counter += ret; 
          return EN_SOC_SUCCESS; 
        } 
      } 
      else 
      { 
        //  bloc 状态,需要等待,直道可以发送 
        if (ret == SOC_WOULDBLOCK) 
        { 
          /* waits for socket notify */ 
          mmi_frm_set_protocol_event_handler(MSG_ID_APP_SOC_NOTIFY_IND, (PsIntFuncPtr)em_soc_demo_app_socket_notify, MMI_TRUE); 
          return EN_SOC_SUCCESS; 
        } 
        else 
        { 
          if (ret == SOC_ERROR) 
          { 
            en_soc_output_result(EN_SOC_PEER_NOT_REACHABLE, NULL, 0); 
            return EN_SOC_PEER_NOT_REACHABLE;
           } 
           else 
          { 
            en_soc_output_result(EN_SOC_ERROR, NULL, 0); 
            return EN_SOC_ERROR; 
          } 
        } 
      } 
    } 
    else 
    { 
      en_soc_output_result(EN_SOC_ERROR, NULL, 0); 
      return EN_SOC_ERROR; 
    } 
  } 
  else 
  { 
    en_soc_output_result(EN_SOC_ERROR, NULL, 0); 
    return EN_SOC_ERROR; 
  } 
}

 

 

转载于:https://www.cnblogs.com/tibetanmastiff/archive/2011/12/29/2305802.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值