APP开发实战32-HTTP Keep-Alive模式介绍

本文介绍了HTTP协议中的Keep-Alive模式,该模式允许连接在多次请求/响应间保持有效,提高了传输效率。内容包括模式简介,以及在没有Content-Length时如何通过Transfer-Encoding:chunked模式来判断数据接收完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

7.6   Keep-Alive模式介绍

7.6.1模式简介

HTTP协议采用“请求-应答”模式,当使用普通模式,即非Keep-Alive模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP协议为无连接的协议);当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接,传输性能更高效。

HTTP1.0中默认是关闭的,需要在HTTP头加入"Connection: Keep-Alive",才能启用Keep-Alive;HTTP1.1中默认启用Keep-Alive,如果加入"Connection: close ",才关闭。

7.6.2判断消息内容/长度的大小

Keep-Alive模式发送玩数据HTTP服务器不会自动断开连接,所有不能再使用返回EOF(-1)来判断。

7.6.2.1 使用消息首部字段Conent-Length

Conent-Length表示实体内容长度,客户端(服务器)可以根据这个值来判断数据是否接收完成。

7.6.2.2 使用消息首部字段Transfer-Encoding

当客户端向服务器请求一个静态页面或者一张图片时,服务器可以很清楚的知道内容大小,然后通过Content-length消息首部字段告诉客户端需要接收多少数据。但是如果是动态页面等时,服务器是不可能预先知道内容大小,这时就可以使用Transfer-Encoding:chunk模式来传输数据了。即如果要一边产生数据,一边发给客户端,服务器就需要使用"Transfer-Encoding:chunked"这样的方式来代替Content-Length。

chunk编码将数据分成一块一块的发生。Chunked编码将使用若干个Chunk串连而成,由一个标明长度为0的chunk标示结束。每个Chunk分为头部和正文两部分,头部内容指定正文的字符总数(十六进制的数字)和数量单位(一般不写),正文部分就是指定长度的实际内容,两部分之间用回车换行(CRLF)隔开。在最后一个长度为0的Chunk中的内容是称为footer的内容,是一些附加的Header信息(通常可以直接忽略)。

Chunk编码的格式如下:

Chunked-Body = *chunk 
                                   "0" CRLF 
                                   footer 
                                   CRLF  
chunk = chunk-size [ chunk-ext ] CRLF 
                 chunk-data CRLF

hex-no-zero = <HEXexcluding "0">

chunk-size = hex-no-zero*HEX 
chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-value ]) 
chunk-ext-name = token 
chunk-ext-val = token | quoted-string 
chunk-data = chunk-size(OCTET)

footer = *entity-header

即Chunk编码由四部分组成:1、0至多个chunk块,2、"0" CRLF,3、footer,4、CRLF.而每个chunk块由:chunk-size、chunk-ext(可选)、CRLF、chunk-data、CRLF组成。

<think>好的,我现在要解决用户的问题,他们使用Charles抓包时遇到了Content-Type是application/octet-stream,没有压缩格式,协议是HTTP/1.0的情况,导致数据乱码和二进制流的问题。 首先,我需要回忆用户之前的问题。用户之前提到普通抓包没有数据,全局代理抓到乱码和二进制流,现在补充了具体的Content-Type和协议信息。这说明数据可能是自定义二进制格式,或者未正确解析。 接下来,分析当前的问题。Content-Type是application/octet-stream,这意味着服务器发送的是任意的二进制数据,没有指定具体类型。HTTP/1.0可能影响数据传输方式,但Charles通常能处理。没有压缩头,所以排除了gzip等因素。 可能的解决方案包括检查数据是否为自定义序列化格式,如Protobuf或MessagePack。用户可能需要导出原始数据并用工具分析。此外,检查是否有SSL解密问题,虽然之前已经配置过,但需要确认是否正确处理了这个特定请求。 另外,考虑是否数据经过加密,比如AES或RSA,这需要逆向工程App的解密方法。或者,数据可能是多媒体文件或特定应用协议,需要对应的解析器。 还要建议用户使用Hex编辑器查看文件头,识别可能的文件类型。同时,确认Charles的配置,确保能够正确显示二进制内容,可能需要调整Viewer或使用自定义解码器。 最后,总结步骤:导出数据、分析结构、尝试反序列化、检查加密、使用工具辅助解析。需要一步步引导用户排查可能的原因,并提供具体的操作命令和方法。</think>根据您描述的情况(Content-Type: application/octet-stream + HTTP/1.0),这种情况通常属于**原生二进制数据传输**,以下是完整的排查和处理方案: --- ### **一、基础特征分析** ```bash # 典型报文特征示例 HTTP/1.0 200 OK Content-Type: application/octet-stream Content-Length: 1024 [二进制数据流] ``` --- ### **二、常见场景与解决方案** #### **1. 自定义二进制协议** **特征**: - 数据头包含魔数(Magic Number)如 `0x89PNG`(PNG图片) - 存在固定长度的包头(如前4字节表示数据长度) **验证方法**: ```bash # 用hexdump查看文件头(前16字节) $ hexdump -C -n 16 received.bin 00000000 50 4b 03 04 14 00 08 00 08 00 00 00 00 00 00 00 |PK..............| → ZIP文件 00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| → PNG图片 ``` #### **2. 未解密的SSL流量** **特殊情况**:即使显示HTTP/1.0,仍可能存在加密 ```bash # 检查Charles的SSL配置 Proxy > SSL Proxying Settings > 确认目标IP:PORT已添加到列表(建议使用通配符 *:443) # 强制刷新证书 Help > SSL Proxying > Reset Charles Root Certificate ``` #### **3. 私有序列化格式** **典型类型**: - Protocol Buffers(需.proto定义文件) - FlatBuffers - Thrift - MessagePack **检测方法**: ```bash # 用xxd查看结构化特征 $ xxd received.bin | head -n 5 00000000: 0800 1224 0a0e 6465 6661 756c 742d 7365 ...$..default-se → Protobuf特征 00000010: 7276 6963 6512 120a 0e64 6566 6175 6c74 rvice....default ``` --- ### **三、实战处理流程** #### **步骤1:导出原始数据** ```bash Charles操作:右键请求 → Export → Save Response Body... 保存为 received.bin ``` #### **步骤2:文件类型鉴定** ```bash # 使用file命令检测(Linux/Mac) $ file received.bin received.bin: PNG image data, 1920 x 1080, 8-bit/color RGB # Windows用户可用TrID工具: trid received.bin ``` #### **步骤3:协议逆向分析** **如果检测不到已知类型**: ```bash # 使用protoc尝试解码(需猜测结构) $ protoc --decode_raw < received.bin 1: 100 2: "secret_data" 3 { 4: 2023 5: 7 6: 25 } ``` #### **步骤4:编程解析(Python示例)** ```python import struct with open('received.bin', 'rb') as f: # 读取固定长度包头(假设前4字节为数据长度) header = f.read(4) data_length = struct.unpack('>I', header)[0] # 大端序解析 # 读取实际数据 payload = f.read(data_length) print(payload.hex()[:20]) # 打印前20字节十六进制 ``` --- ### **四、高级调试技巧** #### **1. 动态Hook(Android Frida)** ```javascript // 拦截Socket写入操作 Interceptor.attach(Module.findExportByName("libc.so", "send"), { onEnter: function(args) { var data = ptr(args[1]).readByteArray(args[2].toInt32()); console.log(hexdump(data, { offset: 0, length: 64 })); } }); ``` #### **2. Wireshark联动** ```bash # 在Charles中导出会话为.pcap格式 File → Export Session → Wireshark/... → 保存为binary_analysis.pcap # 使用Wireshark过滤TCP流 tcp.stream eq 3 → Follow → TCP Stream ``` --- ### **五、特殊注意事项** #### **HTTP/1.0的潜在问题** - 某些旧系统可能使用非标准换行符(如`\r`代替`\r\n`) - 需要检查请求头是否包含`Connection: keep-alive` #### **二进制可视化技巧** ```bash # ASCII艺术化显示(适合含文本的二进制) $ strings received.bin | head -n 10 $ hexyl received.bin | less -R ``` --- 如果经过上述分析仍无法解析,建议提供以下信息以便进一步诊断: 1. 请求的完整URL路径特征(如包含`/binary_stream`等特殊路径) 2. 二进制数据的熵值检测结果(使用`ent`工具) 3. 数据包长度是否固定(如总是512字节的倍数)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值