簡體   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