基于byte[]的HTTP协议头分析代码

最近需要为组件实现一个HTTP的扩展包,所以简单地实现了HTTP协议分析。对于HTTP协议就不详细解说了网上的资料太丰富了,这里主要描述如何通过byte[]流分析出HTTP协议头信息。HTTP协议头有两个协议字符是比较重要的分别就是'\r\n'和':',前者要描述每个头信息的结束,而后则是属性名和属性值的分隔符号。

实现

由于并没有使用Stream来处理所以在分析的时候就不能使用ReadLine来的方便,只能通过分析byte来解决。估计有朋友会问直接把byte[]打包成Stream就方便了,其实主要是使用场问题,有可能一次过来的byte[]包括多个http请求。所以包装成stream用readline的方法成本高不划算。以下看下主体分析代码:

 1         public bool Import(byte[] data, ref int offset, ref int count)
2 {
3 byte[] buffer = mBuffer;
4 while (count > 0)
5 {
6 buffer[mHeaderLength] = data[offset];
7 mHeaderLength++;
8 offset++;
9 count--;
10 if (mHeaderLength >= HEADER_BUFFER_LENGT)
11 throw new NetTcpException("header data too long!");
12 if (mBuffer[mHeaderLength - 1] == mWrap[1] && mBuffer[mHeaderLength - 2] == mWrap[0])
13 {
14 if (Action == null)
15 {
16 Action = Encoding.UTF8.GetString(buffer, mStartIndex, mHeaderLength - mStartIndex - 2);
17 mStartIndex = mHeaderLength;
18 }
19 else
20 {
21 if (mBuffer[mHeaderLength - 3] == mWrap[1] && mBuffer[mHeaderLength - 4] == mWrap[0])
22 {
23 if (mLastPropertyName != null)
24 {
25 this[mLastPropertyName] = Encoding.UTF8.GetString(buffer, mStartIndex, mHeaderLength - mStartIndex - 2);
26 }
27 return true;
28 }
29 else
30 {
31 if (mLastPropertyName != null)
32 {
33 this[mLastPropertyName] = Encoding.UTF8.GetString(buffer, mStartIndex, mHeaderLength - mStartIndex - 2);
34 mStartIndex = mHeaderLength;
35 mLastPropertyName = null;
36 }
37 }
38 }
39 }
40 else if (mBuffer[mHeaderLength - 1] == mNameEof[0] && mLastPropertyName == null)
41 {
42 mLastPropertyName = Encoding.UTF8.GetString(buffer, mStartIndex, mHeaderLength - mStartIndex - 1);
43 mStartIndex = mHeaderLength;
44 }
45
46 }
47 return false;
48
49 }

代码比较简单,通过一次遍历buffer就把Http请求行为和相应用的头属性都分析出来的。由于一个byte[]有可能包括多个HTTP请求(特殊场景),所以参数上使用ref主要是通过外层这个byte[]是否有多个多header要处理。

单元测试

开发人员应该习惯写单元测试,好处是很明显就是实现的代码的可测性,如果可测性差那代码就要从设计上进行调整了。下面是针对以上代码的两种单元测试,主要测试分析代码在不同情况下是否可以良好地工作。

 1 [TestMethod]
2 public void HeaderImport()
3 {
4 string header = "Post\r\nname:henry\r\nemail:\r\n\r\n";
5 byte[] data = Encoding.UTF8.GetBytes(header);
6 int offset = 0;
7 int count = data.Length;
8 byte[] buffer = new byte[1024 * 4];
9 HttpHeader hh = new HttpHeader(buffer);
10 if (hh.Import(data, ref offset, ref count))
11 {
12 Assert.AreEqual(hh.RequestType, "Post");
13 Assert.AreEqual(hh["name"], "henry");
14 Assert.AreEqual(hh["email"], "");
15 }
16
17 }
18
19 [TestMethod]
20 public void HeaderImport1()
21 {
22 string header = "Post\r\nname:henry\r\nemail:henryfan@msn.com\r\n\r\n";
23 byte[] data = Encoding.UTF8.GetBytes(header);
24 int offset = 0;
25 int count = data.Length;
26 byte[] buffer = new byte[1024 * 4];
27 HttpHeader hh = new HttpHeader(buffer);
28
29 if (hh.Import(data, ref offset, ref count))
30 {
31 Assert.AreEqual(hh.RequestType, "Post");
32 Assert.AreEqual(hh["name"], "henry");
33 Assert.AreEqual(hh["email"], "henryfan@msn.com");
34 hh = new HttpHeader(buffer);
35 }
36
37
38 header = "Get\r\nname:henry\r\n";
39 data = Encoding.UTF8.GetBytes(header);
40 offset = 0;
41 count = data.Length;
42 hh.Import(data, ref offset, ref count);
43
44
45 header = "email:henryfan@msn.com";
46 data = Encoding.UTF8.GetBytes(header);
47 offset = 0;
48 count = data.Length;
49 hh.Import(data, ref offset, ref count);
50
51 header = "\r";
52 data = Encoding.UTF8.GetBytes(header);
53 offset = 0;
54 count = data.Length;
55 hh.Import(data, ref offset, ref count);
56
57 header = "\n\r\n";
58 data = Encoding.UTF8.GetBytes(header);
59 offset = 0;
60 count = data.Length;
61
62 if (hh.Import(data, ref offset, ref count))
63 {
64 Assert.AreEqual(hh.RequestType, "Get");
65 Assert.AreEqual(hh["name"], "henry");
66 Assert.AreEqual(hh["email"], "henryfan@msn.com");
67 }
68
69 }
70 }

HttpHeader完整代码

 

基于byte[]的HTTP协议头分析代码的更多相关文章

  1. capwap协议重点分析

    一.     CAPWAP概述 CAPWAP由两个部分组成:CAPWAP协议和无线BINDING协议. (1)CAPWAP协议是一个通用的隧道协议,完成AP发现AC等基本协议功能,和具体的无线接入技术 ...

  2. 基于Qt的A*算法可视化分析

    代码地址如下:http://www.demodashi.com/demo/13677.html 需求 之前做过一个无人车需要自主寻找最佳路径,所以研究了相关的寻路算法,最终选择A算法,因为其简单易懂, ...

  3. HTTP协议及其请求头分析

    HTTP协议及其请求头分析 HTTP协议及其请求头分析   众所周知,Internet的基本协议是TCP/IP协议,目前广泛采用的FTP.Archie Gopher等是建立在TCP/IP协议之上的应用 ...

  4. 基于虎书实现LALR(1)分析并生成GLSL编译器前端代码(C#)

    基于虎书实现LALR(1)分析并生成GLSL编译器前端代码(C#) 为了完美解析GLSL源码,获取其中的信息(都有哪些in/out/uniform等),我决定做个GLSL编译器的前端(以后简称编译器或 ...

  5. UNIX网络编程——分析一帧基于UDP的TFTP协议帧

    下图是UDP的段格式: 相比TCP段格式,UDP要简单得多,也没啥好说的,需要注意的是UDP数据长度指payload加上首部的长度. 下面分析一帧基于UDP的TFTP协议帧: 以太网首部 0000: ...

  6. 分析一帧基于UDP的TFTP协议帧

    下图是UDP的段格式: 相比TCP段格式,UDP要简单得多,也没啥好说的,需要注意的是UDP数据长度指payload加上首部的长度. 下面分析一帧基于UDP的TFTP协议帧: 以太网首部 0000: ...

  7. MySQL二进制日志分析-代码实现(FORMAT_DESCRIPTION_EVENT)

    如前文概述,MySQL Binlog v3以前版本, 二进制日志文件的第一个事件是START_EVENT_V3, 从v4版本开始第一个事件为FORMAT_DESCRIPTION_EVENT(以下简称F ...

  8. Fixed-Length Frames 谈谈网络编程中应用层(基于TCP/UDP)的协议设计

    http://blog.sina.com.cn/s/blog_48d4cf2d0101859x.html 谈谈网络编程中应用层(基于TCP/UDP)的协议设计 (2013-04-27 19:11:00 ...

  9. 苏宁基于Spark Streaming的实时日志分析系统实践 Spark Streaming 在数据平台日志解析功能的应用

    https://mp.weixin.qq.com/s/KPTM02-ICt72_7ZdRZIHBA 苏宁基于Spark Streaming的实时日志分析系统实践 原创: AI+落地实践 AI前线 20 ...

随机推荐

  1. activiti入门2流程引擎API和服务基础设施

    RepositoryService : 管理和控制公布包和流程定义(包括了一个流程每一个环节的结构和行为)的操作 除此之外,服务能够 查询引擎中的公布包和流程定义. 暂停或激活公布包.相应所有和特定流 ...

  2. Flex列在一个表格式的数字值

    1.问题背景 一般的.表格中展示的比率.对照率的处理是:保留两位小数,并向上保留 2.实现实例 <? xml version="1.0" encoding="utf ...

  3. 20天android学习

    20多天的实习(事实上,一个人学习的东西)要结束, 其余的都只有读研. 此20许多天,我学到了很多东西, 至android的发展也有一定的了解.之后写这篇文章主要是完成研究可以学得很快再次回升 1.安 ...

  4. FMDB与GCD

    郝萌主倾心贡献.尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠.支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 因为FMD ...

  5. OData.NET已在 GitHub上开源

    OData.NET已在 GitHub上开源 微软最近已将OData .NET所有类库的源代码全部发布在GitHub上. 以下与OData相关的项目目前都已迁移到GitHub上: ODataLib Ed ...

  6. The Stern-Brocot Number System(排序二进制)

    The Stern-Brocot Number System Input: standard input Output: standard output The Stern-Brocot tree i ...

  7. TRIZ系列-创新原理-28-替代机械系统原理

    替代机械系统原理的详细描写叙述例如以下:1)用光.声.热.嗅觉系统替代机械系统:2)用电.磁或电磁场来与物体交互作用:3)用移动场替代精巧场,用随时间变化的场替代固定场,用结构化的场替代随机场:4)使 ...

  8. JS操作cookie的实例

    <script type="text/javascript"> //写cookies函数 function SetCookie(name, value)//两个参数,一 ...

  9. Beginning Python From Novice to Professional (5) - 条件与循环

    条件与循环 条件运行: name = raw_input('What is your name? ') if name.endswith('Gumby'): print 'Hello, Mr.Gumb ...

  10. 本学习笔记TCP/IP传输协议

    一个.通过网络发送数据,大致能够分为面向有连接与面向无连接两种类型: 1.面向无连接型包含以太网. IP.UDP等协议. 2. 面向有连接 型包含ATM.帧中继.TCP等 协议. 通过一张图了解一下: ...