• HTTP CHUNKED C实现


    C语言不像C#一样有很多很多高度的模块化的东西可以使用,在通讯过程中特别是与http相关的通讯过程中可能要对网站返回的数据做一定处理,而且有不少网站的回应是强制性的,例如向网站请求deflate有个能会返回的是gzip的数据。在这过程中与web特性有关的,在服务器构造消息之前可能并不知道或者不方便知道消息的长度,于是就会将消息分为一段段进行传送。

    例如如下回应:

    不难发现,chunked正式实现这一思想的方式。

    每个HTTP头部含有Transfer-Encoding: chunked则表明此包Data是分块传输的。关于他的介绍痿基百科上说的很多,有兴趣可以看看http://en.wikipedia.org/wiki/Chunked_transfer_encoding

    实质上我们做的工作就是要对HTTP返回的头部含有Transfer-Encoding: chunked的数据做解码工作。

    数据结构如下:长度[HEX] 内容 长度[HEX] 内容

    解码过程当然很简单,没涉及任何数学知识,或者更本谈不上解码,只是做合并工作罢了。。。

    C语言能用的找了10分钟百度不到,除了一段满是奇怪参缺少函数的数狗啃的,索性干脆自己写一个算了。。。

    以下是C(C++)实现代码,在1块长度112下测试通过,应该没什么BUG。有的话烦请只出,代码应该算得上严谨了。

     1 /*
     2  * 十六进制表示的字符串转换为相应的十进制值 传入"7f"返回127
     3  */
     4 int htoi(unsigned char *s) 
     5 { 
     6     int i; 
     7     int n = 0; 
     8     if (s[0] == '0' && (s[1]=='x' || s[1]=='X')) //判断是否有前导0x或者0X
     9     { 
    10         i = 2; 
    11     } 
    12     else 
    13     { 
    14         i = 0; 
    15     } 
    16     for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >='A' && s[i] <= 'Z');++i) 
    17     {   
    18         if (tolower(s[i]) > '9') 
    19         { 
    20             n = 16 * n + (10 + tolower(s[i]) - 'a'); 
    21         } 
    22         else 
    23         { 
    24             n = 16 * n + (tolower(s[i]) - '0'); 
    25         } 
    26     } 
    27     return n; 
    28 } 
    29 
    30 /*
    31 * 查找关键数据串在长数据中出现的位置
    32 * 参数:1长数据指针,2搜索最大长度,3关键字指针,4关键字长度,5搜索起始位置(返回出现位置,若未找到则不变)
    33 * 返回:返回1 成功 返回 0 未找到
    34 */
    35 int _find_key(unsigned char *data,int data_length,unsigned char *key,int key_length,int *position)
    36 {
    37     int i = *position;
    38     if(key == NULL || i<0)
    39     {
    40         return 0;
    41     }
    42     for(; i <= data_length-key_length; i++)
    43     {
    44         if( memcmp(data+i, key, key_length) == 0 )
    45         {
    46             *position = i;
    47             return 1;
    48         }
    49     }
    50     return 0;
    51 }
    52 
    53 /*
    54 * 对HTTP的chunked消息进行合块
    55 * 参数:1待处理数据,2数据长度(分配的长度即可,不一定要求出实际有效长度),3返回合块后的数据,4合块长度
    56 * 算法具有前驱性,返回和传入data可以是同一块内存区域(不建议)
    57 */
    58 int de_chunked(unsigned char *data,int data_length,unsigned char *dest,int *dest_length)
    59 {
    60     char    chunked_hex[CHUNKED_MAX_LEN + 1];    // 十六进制的块长度
    61     int        chunked_len;                        // 块长度
    62     int        ret;
    63     int        begin = 0;
    64     int        end = 0;
    65     int        i = 0;
    66     int        index = 0;
    67 
    68     ret = _find_key(data,data_length,"0
    
    ",5,&end);
    69     if (ret == 0)    //信息不完整
    70         return 0;
    71 
    72     ret = _find_key(data,data_length,"
    
    ",4,&begin);
    73     begin = begin + 4;    //移动到数据起点
    74 
    75     while(memcmp(data+begin,"0
    
    ",5) != 0)
    76     {
    77         //获得当前块长度
    78         ret = _find_key(data+begin,CHUNKED_MAX_LEN,"
    ",2,&i);
    79         if (ret == 0)    //信息不完整
    80             return 0;
    81         memcpy(chunked_hex,data+begin,i);
    82         chunked_hex[i] = '';
    83         chunked_len = htoi(chunked_hex);
    84         //移动到当前块数据段
    85         begin = begin + i + 2;
    86         //获得当前块数据
    87         if (memcmp(data+begin+chunked_len,"
    ",2) != 0)
    88             return 0;    //信息有误
    89         memcpy(dest+index,data+begin,chunked_len);
    90         index = index + chunked_len;
    91         //移动到下一块块长度
    92         begin = begin + chunked_len + 2;
    93         i = begin;
    94         if(begin > end)    //结构错误
    95             return -1;
    96     }
    97     *dest_length = index;
    98     return 1;
    99 }
  • 相关阅读:
    免费部署Woocall到您自己的网站上
    服务器控件开发之复杂属性
    删除数据库的所有存储过程、主键、外键、索引等
    怎样在dropdownlist的每一项前加一个或多个空格
    Java的内部类学习
    StringUtils全览 (转)
    Java异常大全
    Java web 开发小问题总结(持续更新中)
    Java常用方法总结(持续更新中)
    Python 常用函数
  • 原文地址:https://www.cnblogs.com/Huluwa-Vs-Aoteman/p/3635346.html
Copyright © 2020-2023  润新知