Używam dwóch klientów gniazdek obok siebie, zbierając dane strumieniowe http (nie Twitter, ale podobne rzeczy). Dane przechodzą przez kodowane kodowanie.Utrata 6 bajtów, ale tylko wtedy, gdy gniazdo milknie przez 60 sekund?
Jednym z klientów jest curl (w linii poleceń, a nie php-curl), gdzie zarówno http, jak i https działają poprawnie. Drugi to mój własny skrypt PHP, używający fsockopen
i fgets
. Działa dobrze dla https, ale mam specyficzny problem z http. Jak szczegółowe? Dzieje się tak tylko wtedy, gdy strumień cichnie przez 60 sekund. Jeśli jest tylko 50 sekund ciszy, działa dobrze. Porównywałem nagłówki http curl wysyłane i odbierane do mojego skryptu i usunąłem wszystkie różnice. Myślałem, że wiem wszystko, co trzeba wiedzieć o gniazdach PHP, a zwłaszcza kodowanym kodowaniu, ale nadszedł czas, aby zjeść skromne ciasto, ponieważ ten mnie zakłopotał.
Tak, bieganie pozwijane z „--trace - --trace-time”, widzę to przyjść przez dla pierwszego pakietu po 60 sekundowym spokojnym okresie:
05:56:57.025023 <= Recv data, 136 bytes (0x88)
0000: 38 32 0d 0a 7b 22 64 61 74 61 66 65 65 64 22 3a 82..{"datafeed":
0010: 22 64 65 6d 6f 2e 31 64 36 2e 31 6d 2e 72 61 6e "demo.1d6.1m.ran
...
0080: 34 22 7d 5d 7d 0a 0d 0a 4"}]}...
82 hex jest dla wielkości kawałka. \ R \ n oznacza koniec linii wielkości porcji. Fragment zaczyna się od "{".
Powyżej na stronie PHP, moja pętla zaczyna się tak:
while(true){
if(feof($fp)){fclose($fp);return "Remote server has closed\n";}
$chunk_info=trim(fgets($fp)); //First line is hex digits giving us the length
$len=hexdec($chunk_info); //$len includes the \r\n at the end of the chunk (despite what wikipedia says)
https, lub z mniej niż 60 sekund przerwy, to działa dobrze, $ len jest 100 lub niezależnie od wielkości kawałek jest. Ale po tej 60 sekund przerwy, co mogę dostać w $ chunk_info jest:
datafeed":"demo.1d6.1m.ran...
Tak, wydaje mi się, że stracił sześć pierwszych bajtów: 38 32 0d 0a 7b 22
Wszystkie kolejne kawałki są w porządku, a dokładnie tak samo jak to, co otrzymuje loki.
Wersja Szczegóły
curl 7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15 Protokoły: TFTP ftp telnet DICT ldap LDAPS http https plików ftps Cechy: GSS-Negocjuj IDN IPv6 dużyplik NTLM SSL libz
PHP 5.3.2-1ubuntu4.18 z Suhosin-patch (cLI) (wbudowane: Sep 12, 2012 19:12: 47)
Server: Apache/2.2.14 (Ubuntu)
(. Przetestowałem tylko z połączeniami localhost tak daleko)
Reszta pętli wygląda następująco:
$s='';
$len+=2; //For the \r\n at the end of the chunk
while(!feof($fp)){
$s.=fread($fp,$len-strlen($s));
if(strlen($s)>=$len)break; //TODO: Can never be >$len, only ==$len??
}
$s=substr($s,0,-2);
if(!$s)continue;
$d=json_decode($s);
//Do something with $d here
}
(na marginesie: w drodze Przetestowałem dotąd, kod przeszła tej pętli dokładnie raz, przed 60 sekundowym spokojnym okresie.)
UWAGA: Mam wiele sposobów obejścia problemu: wymusić użycie https lub użyć curl-php. To pytanie jest spowodowane tym, że chcę wiedzieć, co się dzieje, wiedzieć, co się zmienia po 60 sekundach i dowiedzieć się, jak to się stało.A może nauczyć się nowego pomysłu na rozwiązywanie problemów. Pomyśl o tym jako o cholernej intelektualnej ciekawości :-)
Z ciekawości: dlaczego nie zaczęliście z PHP CURL? –
Czy możemy zobaczyć resztę twojej pętli, szczególnie część, która zużywa bufor gniazda? –
@FrancisAvila Dzięki za zainteresowanie, właśnie wysłaliście to. –