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]\r\n内容\r\n长度[HEX]\r\n内容\r\n\0\r\n\r\n

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

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

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

 /*
* 十六进制表示的字符串转换为相应的十进制值 传入"7f"返回127
*/
int htoi(unsigned char *s)
{
int i;
int n = ;
if (s[] == '' && (s[]=='x' || s[]=='X')) //判断是否有前导0x或者0X
{
i = ;
}
else
{
i = ;
}
for (; (s[i] >= '' && s[i] <= '') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >='A' && s[i] <= 'Z');++i)
{
if (tolower(s[i]) > '')
{
n = * n + ( + tolower(s[i]) - 'a');
}
else
{
n = * n + (tolower(s[i]) - '');
}
}
return n;
} /*
* 查找关键数据串在长数据中出现的位置
* 参数:1长数据指针,2搜索最大长度,3关键字指针,4关键字长度,5搜索起始位置(返回出现位置,若未找到则不变)
* 返回:返回1 成功 返回 0 未找到
*/
int _find_key(unsigned char *data,int data_length,unsigned char *key,int key_length,int *position)
{
int i = *position;
if(key == NULL || i<)
{
return ;
}
for(; i <= data_length-key_length; i++)
{
if( memcmp(data+i, key, key_length) == )
{
*position = i;
return ;
}
}
return ;
} /*
* 对HTTP的chunked消息进行合块
* 参数:1待处理数据,2数据长度(分配的长度即可,不一定要求出实际有效长度),3返回合块后的数据,4合块长度
* 算法具有前驱性,返回和传入data可以是同一块内存区域(不建议)
*/
int de_chunked(unsigned char *data,int data_length,unsigned char *dest,int *dest_length)
{
char chunked_hex[CHUNKED_MAX_LEN + ]; // 十六进制的块长度
int chunked_len; // 块长度
int ret;
int begin = ;
int end = ;
int i = ;
int index = ; ret = _find_key(data,data_length,"0\r\n\r\n",,&end);
if (ret == ) //信息不完整
return ; ret = _find_key(data,data_length,"\r\n\r\n",,&begin);
begin = begin + ; //移动到数据起点 while(memcmp(data+begin,"0\r\n\r\n",) != )
{
//获得当前块长度
ret = _find_key(data+begin,CHUNKED_MAX_LEN,"\r\n",,&i);
if (ret == ) //信息不完整
return ;
memcpy(chunked_hex,data+begin,i);
chunked_hex[i] = '\0';
chunked_len = htoi(chunked_hex);
//移动到当前块数据段
begin = begin + i + ;
//获得当前块数据
if (memcmp(data+begin+chunked_len,"\r\n",) != )
return ; //信息有误
memcpy(dest+index,data+begin,chunked_len);
index = index + chunked_len;
//移动到下一块块长度
begin = begin + chunked_len + ;
i = begin;
if(begin > end) //结构错误
return -;
}
*dest_length = index;
return ;
}

HTTP CHUNKED C实现的更多相关文章

  1. Transfer-Encoding: chunked

    Http1.1中 使用 chunked 编码传送时 没有CONTENT_LENGTH,下载之前无法确定要下载的大小. Wininet中已经内嵌该传输协议,要查看chunked块的大小只能socket底 ...

  2. NSString asscii格式(2进制) 转 utf8格式——解决iOS自己处理http socket数据,遇到Transfer-Encoding: chunked时

    因为需要实现自己的http客户端,就要自己模拟http 的socket通讯: 上行不难,自己处理好http即可. 但下行时,服务器端的动态语言返回数据有可能会是这种格式: http头 16进制表示的数 ...

  3. HTTP协议的chunked编码

    一般情况HTTP的Header包含Content-Length域来指明报文体的长度.如: 有时候服务生成HTTP回应是无法确定消息大小的,比如大文件的下载,或者后台需要复杂的逻辑才能全部处理页面的请求 ...

  4. 取消掉Transfer-Encoding:chunked

    先说解决方法:::不让服务器返回Transfer-Encoding:chunked,在客户端请求的时候可以使用http 1.0的协议. 有时候,Web服务器生成HTTP Response是无法在Hea ...

  5. 使用SourceTree Push 出现 POST git-receive-pack (chunked) 的解决方法

    在使用SourceTree上传资料的时候,遇到 POST git-receive-pack (chunked) 从 stackoverflow 看到这样一则 This is a bug in Git; ...

  6. 分块编码(Transfer-Encoding: chunked)

    参考链接: HTTP 协议中的 Transfer-Encoding 分块传输编码 一.背景: 持续连接的问题:对于非持续连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界:而对于持续连接,这种 ...

  7. GET 请求复制转发一直等待响应的问题 Transfer-Encoding: chunked

    今天在做Proxy 转发请求的时候发现 GET的请求转发时一直在等待输出. 而Post等其它操作是可以的. 同事告诉我一般一直等待响应可能是输出内容长度和头部ContentLength不一致导致的, ...

  8. 容易被忽视的后端服务 chunked 性能问题

    容易被忽视的后端服务 chunked 性能问题 标签(空格分隔): springboot springmvc chunked 背景 spring boot 创建的默认 spring mvc 项目 集成 ...

  9. HTTP协议扫盲(八 )响应报文之 Transfer-Encoding=chunked方式

    一.什么是chunked编码? 分块传输编码(Chunked transfer encoding)是只在HTTP协议1.1版本(HTTP/1.1)中提供的一种数据传送机制.以往HTTP的应答中数据是整 ...

随机推荐

  1. android:gravity 和 android:layout_Gravity属性

    LinearLayout有两个非常相似的属性: android:gravity 与android:layout_gravity. 他们的区别在于: android:gravity 属性是对该view中 ...

  2. Git hub pull时候的错误 : The current branch is not configured for pull No value for key branch.master.merge found in configuration

    网上多半都是命令行下的解决方案,我用的是EGit,所以要在eclipse里(我的版本是kepler)把下面这句话添加到配置文件中. Window->Preference->Team-> ...

  3. Move Zeroes

    https://leetcode.com/problems/move-zeroes/ Given an array nums, write a function to move all 0's to ...

  4. Linux php 中文乱码解决

    在ubuntu下php网页输出乱码,在不涉及数据库编码的情况下: 修改“/etc/php5/apache2/php.ini”将 default_charset = "iso-8859-1&q ...

  5. substr

    substr(string,start,length) string - 指定的要截取的字符串 start - 必需,规定在字符串的何处开始 正数 - 在字符串的指定位置开始 负数 - 在从字符串结尾 ...

  6. [JavaScript] JS中对Base64的解析

    JS中对Base64的解析 <script type="text/javascript"> /** * UTF16和UTF8转换对照表 * U+00000000 – U ...

  7. ckfinder的配置使用

    1.单纯的上传图片和预览图片 修改configasp中CheckAuthentication = true; 否则的话会报没有权限或修改配置错误 此时如果可以查看的话,单击图片应该是放大并且预览图片 ...

  8. InnoSetup打包exe安装应用程序,并添加卸载图标 转

    http://blog.csdn.net/guoquanyou/article/details/7445773 InnoSetup真是一个非常棒的工具.给我的印象就是非常的精干.所以,该工具已经一步步 ...

  9. python实现线程池

    线程池 简单线程池 import queue import threading import time class ThreadPool(object): #创建线程池类 def __init__(s ...

  10. ubuntu搭建分布式hadoop-2.6.0概略和错误

    详细配置:http://blog.csdn.net/ggz631047367/article/details/42426391 1.修改机器/etc/hostname分别为   master    s ...