基于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. TortoiseGit安装与配置(转)

    TortoiseGit 简称 tgit, 中文名海龟Git. 海龟Git只支持神器 Windows 系统, 有一个前辈海龟SVN, TortoiseSVN和TortoiseGit都是非常优秀的开源的版 ...

  2. 从头学起android<GridView网格视图.二十八.>

    GridView基于组件的网络格所有的形式的组分的,例如:当制作专辑,所有的图片将在相同的尺寸在不同的显示格在孩子,是否能够依靠这个组件完成.此组件的继承结构参见例如下面: java.lang.Obj ...

  3. javascript中event汇总

    原文:javascript中event汇总 ie firefox chrome opera Safari浏览器中对 event的处理并不一致,在此我将各个浏览器中event的兼容处理做了一个汇总,此处 ...

  4. oracle_有关表分区_查询

    <!--查询ORACLE分区表存在多少个分区-->  SELECT * FROM USER_TAB_PARTITIONS WHERE TABLE_NAME='TBL_PAGE';  < ...

  5. projecteuler----&gt;problem=19----Counting Sundays

    You are given the following information, but you may prefer to do some research for yourself. 1 Jan ...

  6. Mac在结构quick cocos2d-x编译环境

    关于 Quick 很多其它的使用说明可參考安装文件夹下的 README 文件. Quick-Coco2d-x开发工具 普通情况下,我们通常都会採用Cocos Code IDE作为开发工具来高速开发游戏 ...

  7. php_windows搭建

    Php文件放到: D:\web\Apache2.2\htdocs 修改 D:\web\PHP\php.ini 拓展 修改 D:\web\Apache2.2\conf\httpd.conf  支持php ...

  8. jg-table 过程2 ( jgTable )

    jg-table ( jgTable )  添加一些新的功能,这是多行表头支持,要添加到,现在支持拖放多行表来改变头部的宽度, 假设设置cloneTheadToFoot 能够自己主动翻转多行表头,这也 ...

  9. jquery 直接调用 wcf,面向服务的SOA架构 ( 第二天)

    在前面的基础上,我们来开始第二天编写 客户端 的东西,不过讲之前,我想告诉大家的是: 这个简单的SOA的架构,我们直接通过wcf 调用到 后台的方法, 而中间没有使用 C#代码,大大减少我们客户端的代 ...

  10. 将已有的工程项目添加到Xcode到Git管理中

    在Xcode中创建工程的时候,我们很容易的可以将新创建的工程添加到Git中,如图: 但是如果是本地已经有的工程,那该如何添加到Git中呢? 首先终端进入到该工程的目录. 然后: git init gi ...