下面通过一段内容有文字说明有代码分析,并附有展示图供大家学习。
要解析HTTP报文,需要实现以下操作:
读取HTTP报头提供的各种属性
分析属性值,从中获取内容编码和字符集编码
将报头数据和内容进行分离
判断内容是否文本还是二进制,如果是二进制的则不进行处理
如果内容是文本,按报头中提供的内容编码和字符集编码进行解压缩和解码
目前没有找到.Net框架内置的解析方法,理论上HttpClient等类在内部应该已经实现了解析,但不知为何没有公开这些处理方法。(亦或是我没找到)
那么只能自己来解析这些数据了。
我们先来看看这个经过gzip压缩的文本内容的HTTP报文:
这里提供一个老外写的简陋的解析类(已经过修改,原代码中存在一些严重BUG):
public enum HTTPHeaderField { Accept = 0, Accept_Charset = 1, Accept_Encoding = 2, Accept_Language = 3, Accept_Ranges = 4, Authorization = 5, Cache_Control = 6, Connection = 7, Cookie = 8, Content_Length = 9, Content_Type = 10, Date = 11, Expect = 12, From = 13, Host = 14, If_Match = 15, If_Modified_Since = 16, If_None_Match = 17, If_Range = 18, If_Unmodified_Since = 19, Max_Forwards = 20, Pragma = 21, Proxy_Authorization = 22, Range = 23, Referer = 24, TE = 25, Upgrade = 26, User_Agent = 27, Via = 28, Warn = 29, Age = 30, Allow = 31, Content_Encoding = 32, Content_Language = 33, Content_Location = 34, Content_Disposition = 35, Content_MD5 = 36, Content_Range = 37, ETag = 38, Expires = 39, Last_Modified = 40, Location = 41, Proxy_Authenticate = 42, Refresh = 43, Retry_After = 44, Server = 45, Set_Cookie = 46, Trailer = 47, Transfer_Encoding = 48, Vary = 49, Warning = 50, WWW_Authenticate = 51 }; class HTTPHeader { #region PROPERTIES private string[] m_StrHTTPField = new string[52]; private byte[] m_byteData = new byte[4096]; public string[] HTTPField { get { return m_StrHTTPField; } set { m_StrHTTPField = value; } } public byte[] Data { get { return m_byteData; } set { m_byteData = value; } } #endregion // convertion System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); #region CONSTRUCTEUR /// <summary> /// Constructeur par défaut - non utilisé /// </summary> private HTTPHeader() { } public HTTPHeader(byte[] ByteHTTPRequest) { string HTTPRequest = encoding.GetString(ByteHTTPRequest); try { int IndexHeaderEnd; string Header; // Si la taille de requête est supérieur ou égale à 1460, alors toutes la chaine est l'entête http if (HTTPRequest.Length <= 1460) Header = HTTPRequest; else { IndexHeaderEnd = HTTPRequest.IndexOf("\r\n\r\n"); Header = HTTPRequest.Substring(0, IndexHeaderEnd); Data = ByteHTTPRequest.Skip(IndexHeaderEnd + 4).ToArray(); } HTTPHeaderParse(Header); } catch (Exception) { } } #endregion #region METHODES private void HTTPHeaderParse(string Header) { #region HTTP HEADER REQUEST & RESPONSE HTTPHeaderField HHField; string HTTPfield, buffer; int Index; foreach (int IndexHTTPfield in Enum.GetValues(typeof(HTTPHeaderField))) { HHField = (HTTPHeaderField)IndexHTTPfield; HTTPfield = "\n" + HHField.ToString().Replace('_', '-') + ": "; //Ajout de \n devant pour éviter les doublons entre cookie et set_cookie // Si le champ n'est pas présent dans la requête, on passe au champ suivant Index = Header.IndexOf(HTTPfield); if (Index == -1) continue; buffer = Header.Substring(Index + HTTPfield.Length); Index = buffer.IndexOf("\r\n"); if (Index == -1) m_StrHTTPField[IndexHTTPfield] = buffer.Trim(); else m_StrHTTPField[IndexHTTPfield] = buffer.Substring(0, Index).Trim(); //Console.WriteLine("Index = " + IndexHTTPfield + " | champ = " + HTTPfield.Substring(1) + " " + m_StrHTTPField[IndexHTTPfield]); } // Affichage de tout les champs /*for (int j = 0; j < m_StrHTTPField.Length; j++) { HHField = (HTTPHeaderField)j; Console.WriteLine("m_StrHTTPField[" + j + "]; " + HHField + " = " + m_StrHTTPField[j]); } */ #endregion } #endregion }
编写以下代码以实现解析文件:
class Program { static void Main(string[] args) { SRART: Console.WriteLine("输入待解析的HTTP报文数据文件完整路径:"); var filename = Console.ReadLine(); try { FileStream fs = new FileStream(filename, FileMode.Open); BinaryReader br = new BinaryReader(fs); var data = br.ReadBytes((int)fs.Length); var header = new HTTPHeader(data); var x = 0; foreach (var f in header.HTTPField) { if (!String.IsNullOrEmpty(f)) { Console.WriteLine($"[{x:00}] - {(HTTPHeaderField) x} : {f}"); } x++; } Console.WriteLine($"总数据尺寸{fs.Length}字节,实际数据尺寸{header.Data.Length}字节"); Console.WriteLine(Encoding.UTF8.GetString(header.Data)); Console.WriteLine(); br.Close(); fs.Close(); } catch (Exception e) { Console.WriteLine(e); } goto SRART; } }
这里还未实现gzip解压缩和字符解码,直接用UTF8解码输出的。(需要时再写吧,都是体力活儿~)
效果图展示:
下面的图是没有经过gzip压缩过的数据。
以上就是用C#如何解析http报文的全部内容,哪位大侠还有好的方法欢迎提出宝贵意见,喜欢大家喜欢以上内容所述。
问题内容: 有谁知道在Python中使用C头文件的好方法吗?例如,我有一个包含全局变量的C程序: 我希望能够采用C编译器/链接器生成的二进制文件,并使用Python脚本解析此结构(并可能对其进行修改)。 问题答案: 看一下用Python编写的C ++标头解析器 。您还可以使用以下任何一种工具编写自己的解析器: 剖析 层 勒普 还有更多…
问题内容: 我从其他地方的日志中附带了http响应标头。在我的日志文件中,我有类似以下内容: 给定上面的字符串,我如何将其解析为net / http中所述的Header对象。一种方法是自己分割字符串并映射键,值…但是我希望避免手动操作,而使用标准的(或维护良好的第3方)库来解析它…任何指针? 问题答案: 内置的解析器位于textproto中。您可以直接使用它,也可以添加伪造的HTTP请求标头并在h
问题内容: 在实现代理服务器时,我将HTTP请求作为字符串发送,如下所示: GET http:// localhost:54321 / x HTTP / 1.1 主机:localhost:54321 缓存控制:无缓存 是否有内置的类来解析此请求? 问题答案: 我对这种解析的内置支持一无所知。如果您确实需要这样的解析器,则可以签出以下库: http //hc.apache.org/index.htm
HTTP请求报文由3部分组成(请求行+请求头+请求体): 下面是一个实际的请求报文: ① 是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。不过,当前的大多数浏览器只支持GET和POST,Spring 3.0提供了一个HiddenHttpMethodFilter,允许你通过“_method”的表单参数指定这些特殊的HTTP
问题内容: 数组: 如何在C#中解析上述json响应 问题答案: 在您提供的字符串 不正确 的格式,该阵列应该是: 您可以使用将其转换: 该工具在nuget中也可用。 如果要使用强类型:
问题内容: 您能否告诉我如何传递如下所示的JSON字符串: 我这样尝试过: 提前致谢 最好的祝福 问题答案: 请注意,您的JSON数据具有以下结构: 顶级值是具有单个属性(称为“课程”)的对象(字典) “教训”属性是一个数组 “课程”数组中的每个元素都是一个具有几个属性的对象(包含课程的字典),其中包括“眩晕” 相应的代码是: 一些观察: 在中,参数是指向指针的指针。在这种情况下,通常使用代替。如