PHP-клиент fsockopen не получает отправленные данные

У меня есть следующий (урезанный) кусок кода:

function curl_request_async($url, $params)
{
foreach ($params as $key => $val) {
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);

$parts=parse_url($url);

$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
fwrite($fp, "$type ".$parts['path']." HTTP/1.1\r\n");
fwrite($fp, "Host: ".$parts['host']."\r\n");
fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
fwrite($fp, "Content-Length: ".strlen($post_string)."\r\n");
fwrite($fp, "Connection: Close\r\n\r\n");

$bytes_written = fwrite($fp, $post_string);
var_dump($bytes_written, strlen($post_string));
// fread($fp, 1);
// fflush($fp);
fclose($fp);
}

Проблема с этим кодом заключается в том, что я не нашел никаких доказательств того, что запрос дошел до вызываемого сервера. Линия var_dump($bytes_written, strlen($post_string)); выводимый int(493) int(493), поэтому он должен был получить все данные, но не получил.

Если я раскомментирую fread($fp, 1); это работает без проблем. Это может быть рабочим решением, но, похоже, это не имеет смысла. Там должен быть лучший путь!

Мой вопрос тогда двоякий: почему fread($fp, 1); исправить мою проблему и есть ли лучшее решение?

0

Решение

Ваша проблема, вероятно, в том, что вы написали серверный код на PHP, и у вас по умолчанию ignore_user_abort = true (см. http://php.net/manual/en/misc.configuration.php#ini.ignore-user-abort ), поэтому, когда вы закрываете соединение, ваш сервер перестает выполнять ваш php-код, поэтому fread (fp, 1) решает вашу проблему — соединение не закрывается до того, как php начнет писать ответ

Вы можете использовать этот код, чтобы заставить сервер проверять, действительно ли он подключается или нет —

<?php
error_reporting(E_ALL);
ini_set('display_errors',1);
$sck=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
if($sck===FALSE){
die('socket_create failed!');
}
if(!socket_set_block($sck)){
die("socket_set_block failed!");
}
if(!socket_bind($sck, '0.0.0.0',1337)){
die("FAILED to bind to port 1337");
}
if(!socket_listen($sck,0)){
die("socket_listen failed!");
}
$fullFile='';
while((print('listening for connections!'.PHP_EOL)) && false!==($conn=socket_accept($sck))){
echo "new connection!".PHP_EOL;
echo "generating crypto iv..";

while(false!==($buffi=socket_recv($conn,$buff,1024,MSG_WAITALL))){
if($buffi===0){
break;//socket_recv's way of
//saying that the connection closed,
//apparently. the docs say it should return
// false, but it doesn't, it just infinitely returns int(0).
// at least on windows 7 x64 sp1.
}
$fullFile.=$buff;
echo "recieved ".strlen($fullFile)." bytes...".PHP_EOL;
$buff='';//do i need to clear it? or wiill recv do it for me?
}
echo "all bytes recieved (i guess, todo, socket_last_error confirm).";
echo PHP_EOL;var_dump($fullFule);
echo "done!".PHP_EOL;
}

die("should never reach this code...");

это сделает сервер в стиле netcat на http://127.0.0.1:1337

1

Другие решения

Для чтения fread нужны два параметра: ресурс и длина в байтах.
Прямо сейчас вы читаете только 1 байт. fread($fp, 1);

Если вы хотите прочитать полный результат, зациклите его, пока не прочитаете полностью:

while(!feof($fp)){
echo fread($fp, 128);
}
0

По вопросам рекламы [email protected]