我一直在並行運行兩個套接字客戶端,收集HTTP流數據(不是Twitter,但類似的東西)。數據通過分塊編碼完成。丟失6個字節,但只有套接字安靜60秒?
其中一個客戶端是curl(在命令行上,而不是php-curl),其中http和https都可以正常工作。另一個是我自己的PHP腳本,使用fsockopen
和fgets
。對https工作正常,但我有一個特定的問題與http。具體如何?只有當流靜音60秒纔會發生。如果只有50秒的安靜,它工作正常。我一直在比較發送和接收到的curl的http頭文件,並刪除了所有的差異。我以爲我知道所有關於PHP套接字的知識,尤其是分塊編碼,但是現在是時候吃下這個蹩腳的餡餅了,因爲這個餡餅已經讓我難住了。
因此,運行具有「--trace - --trace時間」嫋嫋,我看到這個來通過與第一包60秒的平靜期後:
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尺寸爲十六進制的大塊。 \ r \ n標記塊大小行的結尾。該塊從「{」開始。
在在PHP端,我的循環開始像這樣:
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,或者用小於60第二間隙,這工作得很好,$ len爲100或任何塊大小。 但是,有60第二間隙後,我得到$ chunk_info是:
datafeed":"demo.1d6.1m.ran...
所以,我似乎失去了前六個字節:38 32 0d 0a 7b 22
所有後續塊是罰款,並完全與捲曲接收的相同。
版本詳情
捲曲7.19.7下(x86_64-PC-Linux的GNU)的libcurl/7.19.7的OpenSSL/0.9.8k的zlib/1.2.3.3的libidn/1.15 協議:TFTP FTP遠程登錄字典LDAP LDAPS HTTP文件HTTPS FTPS 特點:GSS-協商IDN的IPv6 Largefile NTLM SSL libz進行
PHP 5.3.2-1ubuntu4.18用了Suhosin貼片(CLI)(建:2012年9月12日19:12: 47)
服務器:Apache/2.2.14(Ubuntu的)
(我只與本地主機連接測試,到目前爲止)
循環的其餘部分是這樣的:
$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
}
(旁白:在路上我到目前爲止測試的代碼已經通過這個循環通過恰好一次,60秒靜默期之前。)
注意:我有許多解決方法可以使事情順利進行:例如強制使用https,或使用curl-php。這個問題是因爲我想知道發生了什麼,知道60秒後發生了什麼變化,並學習如何阻止它發生。也許學習一個新的故障排除的想法。把它看作是流血的知識分子的好奇心:-)
好奇心:爲什麼不從PHP的cURL開始? –
我們能否看到循環的其餘部分,尤其是使用套接字緩衝區的部分? –
@FrancisAvila感謝您的興趣,只是發佈它。 –