Здравствуйте, такой вопрос, можно ли сделать тайм аут функции. Допустим вызываю функцию так. Код (Text): $serv=info($r['top']); Если допустим функция не отдала ответ за 3 секунды, то вступало бы в силу код Код (Text): $serv=0; Можно ли такое сделать?
А внутри функция сбора информации. Код (Text): <?php if(!function_exists('getmicrotime')) { function getmicrotime() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } } function cutchar(&$string) { $char = substr($string, 0, 1); $string = substr($string, 1); return $char; } function cutbyte(&$string) { $byte = ord(substr($string, 0, 1)); $string = substr($string, 1); return $byte; } function cutstring(&$string) { $str = substr($string, 0, StrPos($string, chr(0))); $string = substr($string, StrPos($string, chr(0))+1); return $str; } function cutshort(&$string) { $short = substr($string, 0, 2); list(,$short) = @unpack("S", $short); $string = substr($string, 2); return $short; } function cutlong(&$string) { $long = substr($string, 0, 4); list(,$long) = @unpack("l", $long); $string = substr($string, 4); return $long; } function pastelong($long) { return pack("l", $long); } function cutfloat(&$string) { $float = substr($string, 0, 4); list(,$float) = @unpack("f", $float); $string = substr($string, 4); return $float; } function request($request,$server) { list($ip,$port) = explode(":", $server); $request = "\xFF\xFF\xFF\xFF".$request."\x00"; $fp = @fsockopen('udp://'.$ip, $port); if (!$fp) return false; @fwrite($fp, $request); socket_set_timeout($fp, 1); $string=fread($fp, 10240); @fclose($fp); return $string; } function A2A_PING($ip, $port) { $st = request("\x69",$ip,$port); if (!$st) return false; $st = substr($st, 4); if (substr($st, 0, 1) != "\x6A") return false; else return true; } function serverInfo($server) { $timeStart = getmicrotime(); $st = request("\x54Source Engine Query", $server); if (!$st) return false; $st = substr($st, 4); $result['ping'] = (int)((getmicrotime() - $timeStart)*10000); if (substr($st, 0, 1) == "\x49") { $result['status'] = "on"; $result['version_if'] = cutbyte($st); // Byte: Network version $result['version_if2'] = cutbyte($st); // Byte: Network version $result['name'] = cutstring($st); // String: The server's name, eg: "Recoil NZ CS Server #1" $result['map'] = cutstring($st); // String: The current map being played, eg: "de_dust" $result['game'] = cutstring($st); // String: The name of the folder containing the game files, eg: "cstrike" $result['gamename'] = cutstring($st); // String: A friendly string name for the game type, eg: "Counter Strike: Source" $result['id'] = cutshort($st); // Short: Steam Application ID $result['players'] = cutbyte($st); // Byte: The number of players currently on the server $result['max_players'] = cutbyte($st); // Byte: Maximum allowed players for the server $result['bots'] = cutbyte($st); // Byte: Number of bot players currently on the server $result['dedicated'] = cutchar($st); // Char: 'l' for listen, 'd' for dedicated, 'p' for SourceTV $result['os'] = cutchar($st); // Char: Host operating system. 'l' for Linux, 'w' for Windows $result['password'] = cutbyte($st); // Byte: If set to 0x01, a password is required to join this server $result['vac'] = cutbyte($st); // Byte: if set to 0x01, this server is VAC secured $result['gameversion'] = cutstring($st); // String: The version of the game, eg: "1.0.0.14" if($result['version_if'] == 73 && $result['version_if2'] == '48'){ $result['version'] = '47'; }else{ $result['version'] = '73'; } } elseif (substr($st, 0, 1) == "\x6D") { $result['status'] = "on"; $result['type'] = cutchar($st); // Char: 'm' (0x6D) - For GoldSrc $result['ip'] = cutstring($st); // String: Game Server IP address and port $result['name'] = cutstring($st); // String: The server's name, eg: "Recoil NZ CS Server #1" $result['map'] = cutstring($st); // String: The current map being played, eg: "de_dust" $result['game'] = cutstring($st); // String: The name of the folder containing the game files, eg: "cstrike" $result['gamename'] = cutstring($st); // String: A friendly string name for the game type, eg: "Counter Strike: Source" $result['players'] = cutbyte($st); // Byte: The number of players currently on the server $result['max_players'] = cutbyte($st); // Byte: Maximum allowed players for the server $result['version'] = cutbyte($st); // Byte: Network version $result['dedicated'] = cutchar($st); // Char: 'l' for listen, 'd' for dedicated, 'p' for SourceTV $result['os'] = cutchar($st); // Char: Host operating system. 'l' for Linux, 'w' for Windows $result['password'] = cutbyte($st); // Byte: If set to 0x01, a password is required to join this server $result['ismod'] = cutbyte($st); // Byte: If set to 0x01, this byte is followed by ModInfo $result['vac'] = cutbyte($st); // Byte: if set to 0x01, this server is VAC secured $result['bots'] = cutbyte($st); // Byte: Number of bot players currently on the server if ($result['ismod'] == 1) { $result['status'] = "on"; $result['urlinfo'] = cutstring($st); // String: URL containing information about this mod $result['urldl'] = cutstring($st); // String: URL to download this mod $result['nul'] = cutbyte($st); // Byte: 0x00 $result['modversion'] = cutlong($st); // Long: Version of the installed mod $result['modsize'] = cutlong($st); // Long: The download size of this mod $result['svonly'] = cutbyte($st); // Byte: If 1 this is a server side only mod $result['cidll'] = cutbyte($st); // Byte: If 1 this mod has a custom client dll } } else return false; return $result; } function A2S_SERVERQUERY_GETCHALLENGE($server) { $st = request("\x57",$ip,$port); if (!$st) return false; $st = substr($st, 4); if (substr($st, 0, 1) != "\x41") return false; else return cutlong(substr($st, 1)); } function A2S_RULES($server, $challenge) { $st = request("\x56".pastelong($challenge),$ip,$port); if (!$st) return false; $st=substr($st, 4); if (substr($st, 0, 1) == "\x41") { $challenge = cutlong(substr($st, 1)); $st = request("\x56".pastelong($challenge),$ip,$port); if (!$st) return false; $st = substr($st, 4); } if (substr($st, 0, 1) != "\x45") return false; $result['Type'] = cutchar($st); // Char: Should be equal to 'E' $result['Num Rules'] = cutshort($st); // Short: The number of rules reported in response for ($i = 1; $i <= $result['Num Rules']; $i++) { $result['Rule Name'][$i] = cutstring($st); // String: The name of the rule $result['Rule Value'][$i] = cutstring($st); // String: The rule's value } return $result; } function A2S_PLAYER($host) { $st = request("\x55".pastelong($challenge),$host,$port); if (!$st) return false; $st = substr($st, 4); if (substr($st, 0, 1) == "\x41") { $challenge = cutlong(substr($st, 1)); $st = request("\x55".pastelong($challenge),$host,$port); if (!$st) return false; $st = substr($st, 4); } if (substr($st, 0, 1) != "\x44") return false; $result['Type'] = cutchar($st); // Char: Should be equal to 'D' $result['Num Players'] = cutbyte($st); // Byte: The number of players reported in response for ($i = 1; $i <= $result['Num Players']; $i++) { $result['Index'][$i] = cutbyte($st); // Byte: The index into [0.. Num Players] for this entry $result['Player Name'][$i] = cutstring($st); // String: Player's name $result['Kills'][$i] = cutlong($st); // Long: Number of kills this player has $result['Time connected'][$i] = cutfloat($st); // Float: The time in seconds this player has been connected } return $result; } /* function getlistservers(){ //$sql = "SELECT adress FROM amx_servers"; $result = mysql_query($sql); dbquery("SELECT adress FROM amx_servers"); if (mysql_num_rows($result) == 0) { echo "No Servers"; exit; } if (mysql_error()!=='') return mysql_error $result=array(); while ($row=dbarray(adress)) $result[]=$row; // или $result[$row['adress']]=$row так красивее return $result } */ //print_r(serverInfo("95.188.107.104:27037")); //print_r(A2S_RULES("95.31.133.189:27666",A2S_SERVERQUERY_GETCHALLENGE("95.31.133.189:27666"))); //print_r(A2S_PLAYER("91.211.117.26:27017")); ?>
Есть два варианта, первый - считать это время в функции. Второй - использовать ALRM сигнал http://php.ru/manual/function.pcntl-alarm.html, но нужно разобраться, как работают сигналы в php вообще. Ну и это не спасет, если какой-то сокет задумался.
логично предположить, что он просто хочет что-то откуда-то получить по урлу или типа того так что логично установить время обрыва по таймауту при подключении. я не знаю как, но это естественная настройка, наверняка она где-то недалеко.
Вроде есть Код (Text): socket_set_timeout($fp, 1); В коде. Выставлена 1 секунда. Но по каким то причинам если сервер недоступен, он все равно ожидает около 10 секунд, после выбивает что сервер отключен. Добавлено спустя 4 минуты 4 секунды: А не эта ли удача??? Код (Text): <?php $fp = fsockopen ( "udp://127.0.0.1" , 13 , $errno , $errstr ); if (! $fp ) { echo "ERROR: $errno - $errstr<br />\n" ; } else { fwrite ( $fp , "\n" ); echo fread ( $fp , 26 ); fclose ( $fp ); } ?> Но что то разобраться не могу(
возможно ТОТ сервер отвечает тебе с задежкой. т.е. этот таймаут отвечает за облом неудачной попытки соединения. А у тебя возможно она удачная, я тот сервак держит паузу специально.
Хмм, так вот как то нужно поставить таймаут на ответ, даже если он удачный. Нужно обрывать за 1 сек. Не успел сервер за 1 сек ответить, его проблема.
это надо сначала выяснить, где грабли. Ты посмотри детально, на открытие сколько уходит, на каждое чтение сколько. Тогда и ясно будет.
Чтение быстрое. Остановка идет как раз на получение данных. Видимо вы были правы сказав что сервер держит запрос. Коннект есть, а вот данные поступают только через определенное время.
С точностью наоборот. stream_set_timeout отвечает за таймаут чтения/записи. За таймаут подключения отвечает соответствующий аргумент fsockopen. Добавлено спустя 10 минут 21 секунду: Вам нужно делать как-то так Код (Text): stream_set_blocking($fp, FALSE ); stream_set_timeout($sock, $timeout); $info = stream_get_meta_data($sock); while (!feof($sock) && !$info['timed_out']) { $file .= fgets($sock, 4096); $info = stream_get_meta_data($sock); } fclose($sock);