zoukankan      html  css  js  c++  java
  • 基于byte[]的HTTP协议头分析代码

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

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

    实现

    由于并没有使用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
    name:henry
    email:
    
    ";
     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
    name:henry
    email:henryfan@msn.com
    
    ";
    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
    name:henry
    ";
    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 = "
    ";
    52             data = Encoding.UTF8.GetBytes(header);
    53             offset = 0;
    54             count = data.Length;
    55             hh.Import(data, ref offset, ref count);
    56 
    57             header = "
    
    ";
    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完整代码

     View Code
  • 相关阅读:
    HDU 4389 数位dp
    Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1)A B C 水 并查集 思路
    Codeforces Round #385 (Div. 2)A B C 模拟 水 并查集
    Codeforces Round #404 (Div. 2)A B C二分
    HDU 2586 倍增法求lca
    Codeforces Round #209 (Div. 2)A贪心 B思路 C思路+快速幂
    Codeforces Round #384 (Div. 2) A B C D dfs序+求两个不相交区间 最大权值和
    vim出现“E212: Can't open file for writing”的处理办法
    centos7 开机/etc/rc.local 不执行的问题
    CentOS 系统状况查看
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3481306.html
Copyright © 2011-2022 走看看