基于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. 十天学Linux内核之第七天---电源开和关时都发生了什么

    原文:十天学Linux内核之第七天---电源开和关时都发生了什么 说实话感觉自己快写不下去了,其一是有些勉强跟不上来,其二是感觉自己越写越差,刚开始可能是新鲜感以及很多读者的鼓励,现在就是想快点完成自 ...

  2. Lenovo E46A-Win 7_无线灯亮但无法启动(耽误3天以上您信吗.....)问题: wlan autoconfig 依赖服务或组无法启动

    Lenovo E46A-Win 7_无线灯亮但无法启动(耽误3天以上您信吗.....)问题: wlan autoconfig 依赖服务或组无法启动 提示: windows7 无线连接服务wlan au ...

  3. Nyoj 天下第一(spfa)

    描述 AC_Grazy一直对江湖羡慕不已,向往着大碗吃肉大碗喝酒的豪情,但是“人在江湖漂,怎能 不挨刀",”人在江湖身不由己",如果自己的武功太差,在江湖会死的很惨,但是AC_Gr ...

  4. C#按LastID进行分页——与lambda形成链式

    public static class PageHelper { /// <summary> /// 按页码分页 /// </summary> /// <param na ...

  5. csdn 博客,你很努力,有人帮你-2015年03一个月17日本

    今天泛化 开始使用简书 正则表达式的博客写了两篇文章 回顾 Core Data 基本使用 总结 Xcode6新特性 简单聊聊 简书,事实上一開始学 MarkDown 语法的时候,已经用了,但是,一直认 ...

  6. UVA Don&#39;t Get Rooked

    主题如以下:  Don't Get Rooked  In chess, the rook is a piece that can move any number of squaresverticall ...

  7. IntelliJIDEA Getting+Started+with+Spring+MVC,+Hibernate+and+JSON

    https://confluence.jetbrains.com/display/IntelliJIDEA/Getting+Started+with+Spring+MVC,+Hibernate+and ...

  8. Java初始阶段

    初时接触感觉Java与C语言有很多异曲同工之处. Java起源: Java之父:James Gosling 正式发布时间:1995年5月23日 其特点为:简单.面向对象.可移植.多线程.动态 其编译后 ...

  9. NPOI 的使用心得

    Excel 数据  通过 c# 代码逻辑 导入 到数据库  . 其中各种坑爹.原因是 单元格 数据 与 数据库 字段的数据类型 会有出入.因为 Excel 是人工输入. 比如 一个单元格  本来 只能 ...

  10. linux 内核睡眠与唤醒

    休眠(被阻塞)的进程处于一个特殊的不可执行状态.进程休眠由多种原因,但肯定都是为了等待一些事件.事件可能是一 段时间从文件I/O读取更多数据,或者是某个硬件事件.一个进程还由可能在尝试获取一个已被占用 ...