Ahoj,
řeším problém, jak ukončit spojení s klientem tak, aby script mohl pokračovat dál.
Ukázka toho, jak to myslím:
<?php
ignore_user_abort( true );
// Počátek scriptu - nějaký výpisy, zápisy do databáze, ...
echo "ok";
// Ukončení spojení s klientem
// Script po ukončení
// Tady bude nějaký kopírování - třeba 10 giga dat
// Nebo možná nějaký zabalování několika giga dat
// ... prostě věci, které se musí dělat dlouho
?>
Je to kvůli ajaxu, bohužel mi IE čeká až se stáhne celá stránka s výsledkem (ob_fush(); a podobný věci už jsem zkoušel - bohužel neúspěšně :\ )
Fórum › PHP
Jak ukončit spojení s klientem
Nemyslím, že to bude možné tak jednoducho.
Nagooglil som iba takéto riešenie http://www.mail-archive.com/php-general@lists.php.net/msg108210.html.
V skratke: Použiješ register_shutdown_function(). Zavoláš exit() a malo by sa stať že sa spojenie ukončí a vykoná fcia. Ale myslím, že sa čaká na vykonanie funkcie, a spojenie sa ukončí až potom, takže to asi bude na nič.
Napadlo ma ešte, že by sa to dalo vyriešiť tak, že tvoj script by iba spustil nejaký externý proces a skript sám by skončil. Spojenie s browserom by sa uzavrelo, no proces by bežal dalej. Našiel som: http://sk.php.net/manual/en/function.shell-exec.php#73490. No bojím sa, že ak zavoláš ten proces, tak sa tam ten script zastaví, kým sa proces neukončí, a exit môžeš zavolať až potom, takže zasa nič. Prípadne sa skús pohrabať tu: http://sk.php.net/manual/en/book.exec.php.
Ok, iný pohľad - skús ukončiť spojenie na strane klienta, prípadne ho vôbec neukončuj:
Z client-side scriptu (js?) odošli "ajax" request. Spustí sa server-side-script (php). Ten pripraví operáciu, ktorá sa má vykonať, skontroluje, či je všetko o.k. a odošle clientovi odpoveď typu "ok, idem na to" / "uz na tom pracujem" / "uz je to hotove" / "chyba" / etc... Php script sa odpoveďou neukončí, ale začne a bude sa vykonávať operácia...
Na strane klienta však nemusíš čakať až na ukončenie spojenia, ale odpoveď môžeš čítať hňed, ako dorazí. Takže hneď, ako dostaneš zo servera "ok, idem na to", alebo niečo podobné, zavoláš metódu abort() tvojho objektu xmlhttprequest a tým spojenie uzavrieš.
Mimochodom, vôbec neviem, prečo chceš to spojenie uzavrieť. Veď nech tam je. Ak ho nezrušíš, môžeš ho navyše využiť. Z bežiaceho skriptu na serveri môžeš priebežne odosielať priebeh procesu (percenta) a na strane klienta ich budeš môcť sledovať, a zobrazovať napríklad v podobe nejakého dorastajúceho prúžku (progressbaru). Taktiež, ak dôjde ku chybe počas vykonávanie tej operácie, budeš môcť užívateľa hneď informovať....
Dúfam že som ťa aspoň trocha nasmeroval ;-)
# Prog.
register_shutdown_function() + exit(): podle manuálu funguje pouze u PHP < 4.1
shell-exec nechci používat - musel bych zmenšit security pravidla na serveru
Spojení chci uzavřít kvůli mé neznalosti ajaxu a problém s IE - IE mi čeká až příjde celý výsledek stránky a pak pokračuje. Možná to jde ovlivnit na straně js, to jsem nezkoumal.
To Skřivy : Prirodzená cesta na to v php asi existovať nebude, takže na to budeš musieť vymislieť nejakú fintu. Nerozumiem, celkom, že spomínaš iba IE, ostatné browseri reagujú inak ? Ono by to malo závisieť od toho js kódu, čo sa bude robiť. Riešiť tu js a ajax by bolo offtopic.
btw, tiež nerozumiem: zmenšiť security. Veď by si presne nadefinoval práva len na ten jeden shell script na spustenie... Ale ani mne by sa takéto riešenie nepáčilo...
Napadlo ma takéto php riešenie:
JS pošle request na nejaký php script. Ten pošle ďalší request na nejaký iný php script na tom istom serveri a hneď skončí => JS zaznamená koniec spojenia.
Druhý script nastaví ignore_user_abort( true ), vypne timeout a začne pracovať...
poslať request zo servera na server môžeš napr. cez fopen(), s použitím url wrappera, alebo fukciou virtual().
Môže sa jednať aj o jeden a ten istý script, len mu pošleš nejaký param...
Príklad:
do_something.php
<?php
ignore_user_abort( true );
if (@$_GET['do_it'])
{
set_time_limit(0);
switch(@$_GET['cmd'])
{
...
}
}
else
{
set_time_limit ( 5 );
fopen('http://server/do_something.php?cmd='.urlencode(@$_GET['cmd']).'&do_it=1');
}
?>
z js potom len zavolas http://server/do_something.php?cmd=urob_nieco
To Skřivy : Skus ešte tak:
$f = fsockopen("www.server.cz", 80, $errno, $errstr, 5);
if ($f)
{
fwrite($f, "GET /do_something.php?cmd=...&doit=1 HTTP/1.1\r\n".
"Host: www.server.cz\r\n".
"Connection: Close\r\n\r\n");
fclose($f);
}
To Skřivy : Len by som tomu velmi neveril... Chcelo by to ešte prečítať si nejakú odozvu z toho socketu, či sa operácia spustila, lebo teraz nevieš, či nedojde ku chybe. Asi takto:
do_something.php
<?php
ignore_user_abort( true );
if (@$_GET['do_it'])
{
$ready = priprav_operaciu();
if ($ready)
{
echo "OK\r\n"; flush(); // odošle odpoveď
set_time_limit(0);
rob_operaciu();
}
else
{
echo "CHYBA\r\n";
exit();
}
}
else
{
$f = fsockopen("www.server.cz", 80, $errno, $errstr, 5);
if ($f)
{
fwrite($f, "GET /do_something.php?cmd=".urlencode(@$_GET['cmd'])."&doit=1 HTTP/1.1\r\n".
"Host: www.server.cz\r\n".
"Connection: Close\r\n\r\n");
$status = rtrim(fgets($f));
fclose($f);
}
// do ajax odpovede mozes zakomponovať hodnotu v premmennej $status
}
?>
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Vlákna, jak je ukončit — založil Kartmen
Jak ukončit jinou aplikaci — založil Hula
Jak ukončit if bez returnu — založil Draffix
[Java6]Jak ukoncit thread? — založil shadius
ActionScript 3 Jak ukončit tuto funkci? — založil Martin
Moderátoři diskuze