Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> 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 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
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


--------------------
neverever
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.


--------------------
Yes, sex is always the answer, it's never a question
Cos' the answers yes, oh the answers yes.
Not just a suggestion, if you ask the question
Then its always yes, yeah!
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 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. }


--------------------
Yes, sex is always the answer, it's never a question
Cos' the answers yes, oh the answers yes.
Not just a suggestion, if you ask the question
Then its always yes, yeah!
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. }



--------------------
neverever
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 21.08.2025 - 11:27