Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Problem z zatrzymującym się skryptem wysyłającym dane na serwer, funkcja fsockopen(); ma timeout a jednak skrypt nie odpowiada...
marcinpl87
post
Post #1





Grupa: Zarejestrowani
Postów: 21
Pomógł: 0
Dołączył: 22.05.2007

Ostrzeżenie: (0%)
-----


Witam
mam zdefiniowane kilka serwerów które pinguję i w pętli wywołuję wiele razy taki kod:
  1. if ($pinghandle = fsockopen($host, 80, $errno, $errstr, 30)) {
  2. @fputs( $pinghandle, $httpReq );
  3. while (!feof($pinghandle)) {
  4. $pingresponse = @fgets( $pinghandle, 128 );
  5. }
  6. @fclose( $pinghandle );
  7. }
w zmiennej $host mam adres serwera który będę pingował a w $httpReq jest to co do niego wysyłam. Pętla ma kilka tysięcy interacji i przy każdej iteracji mam zapytanie które mi zwiększa o 1 pewien rekord w bazie (to taki mój licznik pingnięć). No i bardzo często (średnio raz na 4 razy) w połowie pętli licznik zatrzymuje się i stoi w miejscu, choć w konsoli widzę że proces jest uruchomiony. Skrypt uruchamiałem albo z crona albo z konsoli bo wykonanie trwa kilka godzin więc jakbym go w przeglądarce uruchomił to raczej miałbym timeouta (IMG:style_emoticons/default/smile.gif) .
Najgorsze jest to że w funkcji fsockopen mam timeout w ostatnim argumencie i nawet jak ustawię ten timeout na 1 sekundę to widzę po komunikatach że ostatni komunikat jest przed tą funkcją i w tym miejscu iteracja pętli się zawiesza.
Podpowiedzcie co tu zrobić żeby zdefiniować jakiś działający timeout żeby w przypadku nie odpowiadającego serwera skrypt jechał dalej i nie zawieszał mi się tak jak teraz.
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 7)
neverever
post
Post #2





Grupa: Zarejestrowani
Postów: 278
Pomógł: 44
Dołączył: 17.02.2004
Skąd: Wieliczka

Ostrzeżenie: (10%)
X----


http://pl.php.net/manual/en/function.stream-set-timeout.php
Go to the top of the page
+Quote Post
marcinpl87
post
Post #3





Grupa: Zarejestrowani
Postów: 21
Pomógł: 0
Dołączył: 22.05.2007

Ostrzeżenie: (0%)
-----


witam, wlepiłem funkcję stream_set_timeout (nie wiem czy w dobrym miejscu) i co kawałek kodu dodałem echo 1 2 3 4 5 6 żebym wiedział w którym momencie skrypt się zatrzymał. Cały ten kod który poniżej wklejam jest wywoływany w pętli wiele razy:
  1. echo $host."\n".'<br />';
  2. echo '1';
  3. if ($pinghandle = fsockopen($host, 80, $errno, $errstr, 10)) {
  4. echo '2';
  5. stream_set_timeout($pinghandle, 10);
  6. echo '3';
  7. @fputs( $pinghandle, $httpReq );
  8. echo '4';
  9. while (!feof($pinghandle)) {
  10. $pingresponse = @fgets( $pinghandle, 128 );
  11. }
  12. echo '5';
  13. @fclose( $pinghandle );
  14. }
  15. else {
  16. echo "TIMEOUT ALBO ERROR: $errno - $errstr<br />\n";
  17. }
  18. echo '6<br />'."\n";
no i gdy skrypt się "zawiesił" zajrzałem do logów i na końcu logu było coś takiego:
  1. blogsearch.google.com
  2. <br />123456<br />
  3. ping.syndic8.com
  4. <br />123456<br />
  5. rpc.blogrolling.com
  6. <br />1234
więc jak widać skrypt zawiesił się gdzieś pomiędzy echo 4 a echo 5, w tej pętli while...
podpowiedzcie proszę - jak to poprawić?

Ten post edytował marcinpl87 13.02.2010, 00:25:44
Go to the top of the page
+Quote Post
yevaud
post
Post #4





Grupa: Zarejestrowani
Postów: 471
Pomógł: 89
Dołączył: 29.07.2008
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


http://php.net/manual/en/function.feof.php
If a connection opened by fsockopen() wasn't closed by the server, feof() will hang.
Go to the top of the page
+Quote Post
XianN
post
Post #5





Grupa: Zarejestrowani
Postów: 57
Pomógł: 9
Dołączył: 12.11.2005
Skąd: ze wnowu?!

Ostrzeżenie: (0%)
-----


Cytat
Warning
If a connection opened by fsockopen() wasn't closed by the server, feof() will hang.


Zobacz do manuala feof, jest tam kod korego mozesz uzyc, aby rozwiazac problem.
Go to the top of the page
+Quote Post
marcinpl87
post
Post #6





Grupa: Zarejestrowani
Postów: 21
Pomógł: 0
Dołączył: 22.05.2007

Ostrzeżenie: (0%)
-----


witam. rozumiem że chodziło o tą pętlę do...while
zmodyfikowałem więc mój kod, teraz wygląda tak:
  1. echo $host."\n".'<br />';
  2. echo '1';
  3. if ($pinghandle = fsockopen($host, 80, $errno, $errstr, 10)) {
  4. echo '2';
  5. stream_set_timeout($pinghandle, 10);
  6. echo '3';
  7. @fputs( $pinghandle, $httpReq );
  8. echo '4';
  9. do {
  10. $pingresponse = @fgets( $pinghandle, 128 ); //wysyla dane o pingu
  11. } while (!feof($pinghandle));
  12. fclose($pinghandle);
  13. }
  14. echo '6<br />'."\n";
ale skrypt znowu zatrzymuje się po 1234 czyli przed do{}
co robię źle?
Go to the top of the page
+Quote Post
XianN
post
Post #7





Grupa: Zarejestrowani
Postów: 57
Pomógł: 9
Dołączył: 12.11.2005
Skąd: ze wnowu?!

Ostrzeżenie: (0%)
-----


No wlasnie nie o to (IMG:style_emoticons/default/winksmiley.jpg) Teraz mozesz poczytac czym rozni sie while... od do...while (czyli tym, ze do... zrobi przynajmniej raz costam, sprawdzanie warunku petli wykonuje sie _PO_ wykonaniu petli)

A chodzi o to, ze fgets ma zabrac 127 bitow, ew linie ze znakiem jej konca lub napotkac koniec strumienia. Jesli trafisz na serwer, ktory nie zamyka socketa poprawnie to zawisniesz w tym miejscu, bo feof dalej zwraca false, z fgets nie ma juz nic do przeczytania. Zastosuj ten kod z safe_feof.

To moze byc jakos tak (nie mam teraz czasu, zeby zobaczyc czy to bedzie poprawnie...):
  1. <?php
  2. function safe_feof($fp, &$start = NULL) { // w manualu tutaj jest literowka
  3. $start = microtime(true);
  4.  
  5. return feof($fp);
  6. }
  7.  
  8. $start = NULL;
  9. $timeout = ini_get('default_socket_timeout');
  10.  
  11. echo $host."\n".'<br />';
  12. echo '1';
  13.  
  14. if ($pinghandle = fsockopen($host, 80, $errno, $errstr, 10))
  15. {
  16. @fputs( $pinghandle, $httpReq ); // to wysyla...
  17.  
  18. while(!safe_feof($fp, $start) && (microtime(true) - $start) < $timeout)
  19. {
  20. $pingresponse = @fgets( $pinghandle, 128 ); //wysyla dane o pingu <---- wcale nie! To nie wysyla, tylko odbiera informacje [!!!!!!]
  21. }
  22. fclose($pinghandle);
  23. }
  24. else
  25. {
  26. echo 'cos nie poszlo';
  27. }


A tak poza tym, to dlaczego uparles sie na socket? Chcesz zobaczyc czy dziala serwis, to zamiast robic to w ten sposob mozesz uzyc file_get_contents:
  1. $opts = array(
  2. 'http'=>array(
  3. 'method'=>"GET",
  4. 'header'=>"Accept-language: en\r\n" .
  5. "Cookie: foo=bar\r\n"
  6. )
  7. );
  8.  
  9. if ($context = stream_context_create($opts))
  10. {
  11. if (file_get_contents('http://www.google.pl/', false, $context, 0, 10)) // z ograniczeniem na dane, bo nie obchodzi nas co tam jest tylko czy w ogole jest cokolwiek
  12. {
  13. echo 'dziala';
  14. }
  15. }
Go to the top of the page
+Quote Post
neverever
post
Post #8





Grupa: Zarejestrowani
Postów: 278
Pomógł: 44
Dołączył: 17.02.2004
Skąd: Wieliczka

Ostrzeżenie: (10%)
X----


Cytat(marcinpl87 @ 13.02.2010, 02:23:49 ) *
witam, wlepiłem funkcję stream_set_timeout (nie wiem czy w dobrym miejscu) i co kawałek kodu dodałem echo 1 2 3 4 5 6 żebym wiedział w którym momencie skrypt się zatrzymał. Cały ten kod który poniżej wklejam jest wywoływany w pętli wiele razy:

Najpierw wypadało trochę poczytać z podanego linka, no i warto by zerknąć w przykłady poniżej.
Wiedział byś wtedy jak to stosować.

  1. if ($pinghandle = fsockopen($host, 80, $errno, $errstr, 30)) {
  2. @fputs( $pinghandle, $httpReq );
  3.  
  4. stream_set_timeout($pinghandle, 2);
  5. $info = stream_get_meta_data($pinghandle);
  6.  
  7. while (!feof($pinghandle) && (!$info['timed_out'])) {
  8. $pingresponse = @fgets( $pinghandle, 128 );
  9. $info = stream_get_meta_data($pinghandle);
  10. }
  11. @fclose( $pinghandle );
  12. }

Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 23.08.2025 - 07:47