2009-10-07 18 views
7

如果我有一个很大的HTTP数据包已被分解为多个TCP数据包,我怎样才能将它们重建为单个HTTP数据包?基本上,在数据包中,我希望告诉HTTP数据包何时开始/结束?我似乎看不到任何表示HTTP数据包开始或结束的TCP标头中的标志/字段。HTTP数据包重建

编辑:在跟进的回应。如果TCP管理流,它如何知道流何时开始和结束?这是由插座打开和关闭决定的吗?有些协议在某种程度上必须能够知道HTTP流/数据包何时开始和结束。这是我想知道的。

我现在的情况是我在C#中使用了一个包嗅探器,它读取TCP数据包,我希望能够重建HTTP请求/响应/等。像Wireshark和其他各种嗅探器所做的那样经历界面。或者,是否有任何C#库允许您在更高级别上使用HTTP流,从而使我不必自己重新构建HTTP流/数据包?

谢谢。

回答

10

好吧,我制定了如何做到这一点(狡猾,但它完成了工作)。

剥离以太网,IP和TCP标头很简单,只留下'原始'数据信息。从消息内部看,通过在数据包的开始处查找“HTTP/1.1 ...”,很容易检测它是否是HTTP数据包的开始。这表明数据包是HTTP流/更大数据包/无论什么的开始。你也可以做一些简单的解析来读取“Content-Length”字段,它是整个HTTP数据包的总长度。

您也可以使用源/目标IP &端口号为链接形成唯一的ID。因此,在收到标头数据包之后,请注意这4件事情(SRCIP,SRCPORT,DESTIP,DESTPORT)。下次您收到一个匹配此端口/ IP组合的数据包时,您可以检查它是否是HTTP数据包的下一部分。你可以使用序列号来做一些验证,也可能是其他的东西,但通常这些数据包是按顺序排列的,所以没关系。我认为每个HTTP流都会打开一个新端口,因此您不应该收到不属于流的随机数据包,但这可能是一个容易出错的区域。

无论如何,一旦你收到这个包,再次剥离标题并获得原始信息。将其添加到消息的已知部分。如果到目前为止收到的总消息长度等于从“Content-Length”字段中读取的长度,则数据包完成!

这种方法显然容易出现大量的错误,但我并没有采取一种非常稳健的方式。我想我会回答我自己的问题,以防其他人在未来遇到同样的问题!你的嗅探好运:D

+2

如果没有指定的Content-Length字段,还有其他的方式来锻炼身体的长度了。例如http://www.httpwatch.com/httpgallery/chunked/ – mike

+2

可能有点迟,但是'Content-Length'头没有指定总包长度。它只是指定了内容的大小,即标题之后的主体。标题和正文由'\ r \ n \ r \ n'分隔。 –

7

您不应该使用TCP级别的任何信息来确定HTTP请求边界。 TCP提供可靠的字节流服务;你不能在TCP中看到任何字段或标志,因为它们不在那里。

要确定HTTP请求中边界的位置,您应该遵循RFC 2616.边界定义良好,您可以通过解析接收到的数据来确定边界。

2

TCP是协议,而不是分组协议。应用程序层(即您)获取数据流,而不是一堆数据包。你只需从流中读取字节,你就可以得到你的整个http载荷,而TCP会在下面进行错误检查,重新发送等。

4

在每个TCP数据包中,有效负载数据的起始位置紧跟在TCP报头之后,并且有效负载数据的末尾是IP数据包的结尾。

TCP头部的末尾很容易找到 - Data Offset是头部中的一个4位字段,其中包含32位字的头部长度(因此,将其乘以4以得到长度为8位的字长)位字节)。

使用Sequence字段中的TCP序列号以正确的顺序将有效负载串起来。请注意,在重传的情况下可能会有重复。

1

我们必须努力解决同样的问题。我们能够在开源项目中提取一些核心功能。

http://code.google.com/p/pcap-reconst/

请你检查出来,让我知道,如果它帮助你。

+0

我对使用您的代码感兴趣。无需深入研究源代码,您的项目是否可以处理a)基于Content-Encoding标头对压缩数据进行解压缩,b)根据Content-Type中的charset转换为通用文本编码头和C)处理分块编码时,“Transfer-Encoding”头设置为“分块”? –