[英]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代碼,但是沒有發現任何東西。
所以我的問題是:
非常感謝。
更新:
我嘗試了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.