我们正在尝试实现代理概念验证,但遇到了一个有趣的问题:由于单个HTTP连接可以,实际上应该发出多个请求,并且由于TCP的魔力,HTTP事务通过多个数据包发送, HTTP请求是否可以在数据包中间开始?
请记住,这不是关于浏览器可能优化的理论问题,而是它是否真的发生在现实生活中。如果有人可以指出我是否有可能的书面参考,如果可能的话,它会发生的频率会更好。
澄清更新:我们知道如果我们单独在HTTP层工作,我们就不需要为这个问题烦恼了,但是我们试图通过首先处理TCP层来确定是否可以应用某些高级技术。
答案 0 :(得分:3)
首先,TCP是基于流的协议,没有数据包的概念。 HTTP本身可能有某种消息或记录分隔符,但TCP没有。
此页面可能会有所帮助:Structure of HTTP Transactions
从您的问题来看,您认为从TCP套接字读取的每个内容都是数据的“数据包”。实际上,每个读取只读取缓冲区中的字节数,直到您请求的最大值,而没有任何记录或数据包的概念。
例如,假设您从套接字读取2048个字节,您可以拥有一个事务的尾部,然后在您读取的数据的一半开始第二个响应,并且只获得剩余的下次从套接字读取时的第二个响应。
如果你在耶路撒冷或附近,也许我可以帮助你。
答案 1 :(得分:3)
假设您正在谈论IP数据包:是的,HTTP请求可能从IP数据包的中间开始。
当您使用持久性HTTP connections时,即对多个HTTP请求使用相同的TCP连接时,请求边界完全可能是IP数据包的中间位置。
IP和HTTP之间也有TCP协议。 TCP还包含一些标头,因此IP数据包可能从某些TCP标头开始,而其余数据包则包含HTTP请求。
HTTP请求也可能包含多个IP数据包(如果是文件上传,传输错误和后续重传等)。
但是,如果您在HTTP级别工作,我想知道为什么您对数据包感兴趣。 TCP应隐藏IP数据包详细信息。
答案 2 :(得分:0)
取决于您正在讨论的数据包的哪个抽象层:HTTP下面有许多层。
HTTP --> TCP (byte stream) --> IP (packet) --> (possibly something else) Ethernet (frame) --> (possibly) some other transport
如果你在谈论IP层,那么HTTP层将在稍后开始...注意,TCP向其客户层提供“字节流接口”,因此,这里没有包的概念。
答案 3 :(得分:0)
除非您正在实现自己的TCP堆栈,否则您不必担心数据包,而是担心TCP提供的API,如果是POSIX接口,它将是recv()或read()。所以我将问题视为“可以将多个HTTP请求放入单个read()中,并且可以在多个read()请求之间分配HTTP请求吗?” - 两者的答案都是“是的,有可能”。
可能发生这种情况的一个例子是HTTP pipelining。这在现实生活中并不常见(具有讽刺意味的是,至少有些浏览器默认禁用它,因为“buggy proxies”:-) - 但是当它发生时,对于用户诊断来说可能有点问题 - 特别是如果它们无法访问代理。
在Debian派生的Linux系统中,默认apt-get确实发生了一个非常值得注意的地方。只需安装Debian或Ubuntu服务器并尝试通过代理使用它。您可以通过编辑 /etc/apt/apt.conf.d/proxy 文件并在其中放置以下内容来执行此操作:
Acquire::http::Proxy "http://your.proxy.address:8080";
答案 4 :(得分:0)
我想我明白你在试图回答这个问题。
如果您不使用持久HTTP连接,HTTP GET请求标头始终是通过TCP连接发送的第一件事,因此我们可以确保HTTP GET请求标头的开头“无法启动”在一些TCP数据包的中间“。但请记住,可能存在一个或多个没有任何用户数据的TCP数据包,例如只有一个SYN,它可能在TCP数据包之前,带有HTTP GET请求头的开头。并且还要记住,HTTP GET请求标头可能不包含在单个TCP数据包中。
如果您使用持久HTTP连接,请求号N + 1的HTTP GET请求标头的开始可以在TCP数据包的中间开始,即在请求号N的HTTP GET请求主体结束之后。< / p>
如果你问这些问题,你可能“做错了”。正如其他几位响应者已经指出的那样,在绝大多数情况下,您应该只是一个TCP客户端并处理TCP数据流并让TCP代码担心TCP数据包。 (当然,除非你正在研究一些特殊的硬件,它们在飞过时会查看单个IP数据包并尝试在HTTP层进行一些处理。)