繁体   English   中英

如何使用PHP套接字获取HTTP响应

[英]How to get an HTTP response using PHP sockets

我需要编写一个PHP脚本,该脚本使用本地代理(鱿鱼)“执行” HTTP请求。 从客户端接收到HTTP请求,脚本将请求发送到代理,从代理接收HTTP响应,并在进行一些处理后将其返回给客户端。 我知道您会告诉我有关此方法的所有坏消息,但请相信我,我需要这样做。

我正在使用PHP套接字来实现这一点。 这是我尝试中继请求的代码片段(基于我在网络上找到的示例):

<?php 
$PROXY="localhost";
$PORT="3128";
$BUFFER_SIZE=1024*1024*5; //5Mb buffer

// (An untested HTTP request example, replace if it is not correct pls)
$request = "GET http://www.google.com HTTP/1.1\nHost: www.google.com\n\n";

// Create socket
if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0)))
{
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    die("Couldn't create socket: [$errorcode] $errormsg\n");
}

//Connect socket to proxy server
if(!socket_connect($sock , $HOST , $PORT))
{
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    die("Could not connect: [$errorcode] $errormsg\n");
}

//Send the message to the proxy
if( ! socket_send ( $sock , $request, strlen($request) , 0))
{
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode); 
    die("Could not send data: [$errorcode] $errormsg\n");
}

//Now receive reply from proxy
if(socket_recv ( $sock , $buf , $BUFFER_SIZE , MSG_WAITALL ) === FALSE)
{
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode); 
    die("Could not receive data: [$errorcode] $errormsg\n");
}

//print the received message
print $buf;

该代码将消息发送到代理,但是...被阻止。 经过研究后,我发现了问题所在:脚本等待直到至少接收到BUFFER_SIZE个字节或关闭连接。

我可以避免设置超时选项:

if(!socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,array("sec"=>2, "usec"=>0)))
{   $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    die("Can't set options: [$errorcode] $errormsg\n");
};

但这不能解决我的问题,因为我想接收整个HTTP响应,并且请求可以是HTTP 1.1

我一直在考虑它,而我唯一的想法是编写代码以分析HTTP响应以查看其结束位置。 我一直在搜索一些PHP代码,但是没有发现任何东西。

所以我的问题是:

  • 有没有一种方法可以将整个HTTP响应存储到缓冲区中而不进行解码?
  • 有没有一种简单的方法可以用PHP解码HTTP响应?
  • 有没有更简单的方法可以在不使用套接字的情况下向代理发送和接收请求?

非常感谢。

更新:

我尝试了Maskime建议的循环。 这是代码:

while($response=socket_recv ( $sock , $buf , 1 , MSG_WAITALL ))
{
    ...
    print $buf;
} 

它读取数据并在超时到达时(而不是在此之前)退出。 我不能使用这种方法,因为如果我设置了超时,则所有请求将至少遭受该延迟,并且如果我将其设置得太低,则某些请求将没有时间加载。

经过一番调查,看来您需要“解码” HTTP / 1.1响应才能正确处理它。 我没有找到需要的库来执行此操作,因此尝试了另一种方法。

我所做的是在代理级别修改请求,以使连接变为非持久性。 为此,您需要在squid.conf中设置此指令(也许仅其中一部分就足够了,但是我还没有尝试过):

client_persistent_connections off
server_persistent_connections off
persistent_connection_after_error off

使用该配置,它可以按我的要求工作。 将接收超时时间调整为两秒以上是个好主意,否则很多请求将丢失。 十秒钟对我来说可以正常工作,但可能会更长:只有在真正超时的情况下,它才会提高。

我想知道对第二个问题的回答,如果您有想法,最好知道。 我一直在研究Snoopy库,但是它可以与HTTP / 1.0一起使用,并且没有进一步研究。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM