9

如果我有一个大的 HTTP 数据包,它已被拆分为多个 TCP 数据包,我如何将它们重新构建为单个 HTTP 数据包?基本上,我在数据包中的哪个位置查看 HTTP 数据包何时开始/结束?我似乎看不到 TCP 标头中表示 HTTP 数据包开始或结束的任何标志/字段。

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

我所处的情况是我在 C# 中使用数据包嗅探器读取 TCP 数据包,并且我希望能够重建 HTTP 请求/响应/等。像wireshark和其他各种嗅探器一样通过界面。或者,是否有任何 C# 库可以让您在更高级别访问 HTTP 流,从而让我不必自己重建 HTTP 流/数据包?

谢谢。

4

6 回答 6

14

好的,我想出了如何做到这一点(狡猾但它完成了工作)。

剥离以太网、IP 和 TCP 报头很简单,只剩下“原始”数据消息。查看消息内部,通过在数据包开头查找“HTTP/1.1 ...”很容易检测它是否是 HTTP 数据包的开头。这表明数据包是 HTTP 流/更大数据包/其他的开始。您还可以做一些简单的解析来读取“Content-Length”字段,它是整个 HTTP 数据包的总长度。

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

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

这种方法显然容易出现大量错误,但我并不追求一种非常健壮的方法。我想我会回答我自己的问题,以防其他人将来遇到同样的问题!祝你嗅探好运:D

于 2009-10-08T04:15:31.797 回答
8

您不应使用 TCP 级别的任何信息来确定 HTTP 请求边界。TCP提供可靠的字节流服务;您在 TCP 中看不到任何有助于解决此问题的字段或标志,因为它们不存在。

要确定 HTTP 请求中的边界在哪里,您应该遵循 RFC 2616。边界是明确定义的,您可以通过解析接收到的数据来确定它们。

于 2009-10-07T05:41:20.550 回答
5

在每个 TCP 数据包中,有效负载数据的开始紧接在 TCP 标头之后,有效负载数据的结尾是 IP 数据包的结尾。

TCP 标头的结尾很容易找到 - 标头中的Data Offset一个 4 位字段包含以 32 位字表示的标头长度(因此将其乘以 4 以获得以 8 位字节为单位的长度)。

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

于 2009-10-07T06:30:07.220 回答
3

TCP 是协议,而不是数据包协议。应用层(即你)得到一个数据流,而不是一堆数据包。您只需继续从流中读取字节,您将获得整个 http 有效负载,而 TCP 在下面进行错误检查、重新发送等。

于 2009-10-07T05:47:28.853 回答
3

您可以使用名为 Xplico 的开源项目的代码: http ://www.xplico.org

于 2010-06-23T10:03:59.670 回答
2

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

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

请检查一下,如果它对您有帮助,请告诉我。

于 2009-11-12T16:55:32.583 回答