国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開(kāi)發(fā) > PHP > 正文

關(guān)于PHP 如何用 curl 讀取 HTTP chunked 數(shù)據(jù)

2024-05-04 23:43:20
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
通過(guò)本文給大家介紹php用curl讀取http chunked數(shù)據(jù)的方法,本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
 

對(duì)于 Web 服務(wù)器返回的 HTTP chunked 數(shù)據(jù), 我們可能希望在每一個(gè) chunk 返回時(shí)得到回調(diào), 而不是所有的響應(yīng)返回后再回調(diào). 例如, 當(dāng)服務(wù)器是 icomet 的時(shí)候.

在 PHP 中使用 curl 代碼如下:

<?php $url = "http://127.0.0.1:8100/stream";$ch = curl_init($url);curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'myfunc');$result = curl_exec($ch);curl_close($ch);function myfunc($ch, $data){$bytes = strlen($data);// 處理 datareturn $bytes;}

但是, 這里有一個(gè)問(wèn)題. 對(duì)于一個(gè) chunk, 回調(diào)函數(shù)可能會(huì)被調(diào)用多次, 每一次大概是 16k 的數(shù)據(jù). 這顯然不是我們希望得到的. 因?yàn)?icomet 的一個(gè) chunk 是以 "/n" 結(jié)尾, 所以回調(diào)函數(shù)可以做一下緩沖.

function myfunc($ch, $data){$bytes = strlen($data);static $buf = '';$buf .= $data;while(1){$pos = strpos($buf, "/n");if($pos === false){break;}$data = substr($buf, 0, $pos+1);$buf = substr($buf, $pos+1);// 處理 data}}

下面給大家介紹下chunked php使用fsockopen讀取分段數(shù)據(jù)(transfer-encoding: chunked)

使用fsockopen讀取數(shù)據(jù)時(shí)遇到了一個(gè)神奇的問(wèn)題,具體情況如下:

讀取地址:http://blog.maxthon.cn/?feed=rss2

讀取代碼:

<?php$fp = fsockopen("blog.maxthon.cn", 80, $errno, $errstr, 30);if (!$fp) {echo "$errstr ($errno)<br />/n";} else {$out = "GET /?feed=rss2 HTTP/1.1/r/n";$out .= "Host: blog.maxthon.cn/r/n";$out .= "Connection: Close/r/n/r/n";fwrite($fp, $out);while (!feof($fp)) {echo fgets($fp, 128);}fclose($fp);}?>

返回http內(nèi)容:

Date: Mon, 29 Mar 2010 10:16:13 GMTServer: Apache/2.2.8 (Unix) mod_ssl/2.2.8 OpenSSL/0.9.8b PHP/5.2.6X-Powered-By: PHP/5.2.6X-Pingback: http://blog.maxthon.cn/xmlrpc.phpLast-Modified: Wed, 03 Mar 2010 03:13:41 GMTETag: "8f16b619f32188bde3bc008a60c2cc11"Keep-Alive: timeout=15, max=120Connection: Keep-AliveTransfer-Encoding: chunkedContent-Type: text/xml; charset=UTF-822de<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"<description><![CDATA[2009年12月31日1711.......1fe8]]></description><content:encoded><![CDATA[<p>2009年12月31日<br />1711</p>

請(qǐng)注意上面那些標(biāo)紅的4個(gè)字符,它們每隔一段數(shù)據(jù)就會(huì)出現(xiàn)一次,但是用其他的方法如curl,file_get_contents等取回的數(shù)據(jù)則沒(méi)有這些玩意。換成其他的網(wǎng)站來(lái)抓取,也只是少數(shù)的網(wǎng)站會(huì)出現(xiàn)這種情況,多方搜索無(wú)解后,我無(wú)意中看到了上面返回頭中有這么一個(gè)聲明:Transfer-Encoding: chunked,而常見(jiàn)的Content-lenght字段沒(méi)有了。這個(gè)聲明的大致的意思是傳輸編碼為分段方式。

在Google上搜索該關(guān)鍵詞,在維基百科上找到對(duì)這個(gè)聲明的解釋?zhuān)ㄓ捎跊](méi)有中文版,我只能自己按照意思翻譯):

Chunked Transfer Encoding is a mechanism that allows HTTP messages to be split in several parts. This can be applied to both HTTP requests (from client to server) and HTTP responses (from server to client)

分塊傳輸編碼是一種機(jī)制,允許將HTTP消息分成幾個(gè)部分傳輸。同時(shí)適用于HTTP請(qǐng)求(從客戶(hù)端到服務(wù)器)和 HTTP響應(yīng)(從服務(wù)器到客戶(hù)端)

For example, let us consider the way in which an HTTP server may transmit data to a client application (usually a web browser). Normally, data delivered in HTTP responses is sent in one piece, whose length is indicated by the Content-Length header field. The length of the data is important, because the client needs to know where the response ends and any following response starts. With chunked encoding, however, the data is broken up into a series of blocks of data and transmitted in one or more "chunks" so that a server may start sending data before it knows the final size of the content that it's sending. Often, the size of these blocks is the same, but this is not always the case.

例如,讓我們考慮HTTP服務(wù)器可將數(shù)據(jù)傳輸?shù)娇蛻?hù)端應(yīng)用程序(通常是一個(gè)網(wǎng)絡(luò)瀏覽器)使用哪些方式。通常情況下,在HTTP響應(yīng)數(shù)據(jù)是按照一整塊發(fā)送給客戶(hù)端的,數(shù)據(jù)的長(zhǎng)度是由Content - Length頭域表示。數(shù)據(jù)的長(zhǎng)度很重要,因?yàn)榭蛻?hù)需要知道在哪里響應(yīng)結(jié)束和后面的響應(yīng)何時(shí)啟動(dòng)。而使用Chunked編碼方式,不管怎樣,數(shù)據(jù)都會(huì)分割成一系列的數(shù)據(jù)塊和一個(gè)或多個(gè)轉(zhuǎn)發(fā)的“塊”,因此服務(wù)器在知道內(nèi)容的長(zhǎng)度之前,就可以開(kāi)始發(fā)送數(shù)據(jù)后。通常情況下,這些數(shù)據(jù)塊的大小是一樣的,但也并不是絕對(duì)的。

大概意思了解后,我們來(lái)看例子:

Chunked編碼使用若干個(gè)Chunk串連而成,由一個(gè)標(biāo)明長(zhǎng)度為0的chunk標(biāo)示結(jié)束。每個(gè)Chunk分為頭部和正文兩部分,頭部?jī)?nèi)容指定下一段正文的字符總數(shù)(十六進(jìn)制的數(shù)字)和數(shù)量單位(一般不寫(xiě)),正文部分就是指定長(zhǎng)度的實(shí)際內(nèi)容,兩部分之間用回車(chē)換行(CRLF)隔開(kāi)。在最后一個(gè)長(zhǎng)度為0的Chunk中的內(nèi)容是稱(chēng)為footer的內(nèi)容,是一些附加的Header信息(通常可以直接忽略)。具體的Chunk編碼格式如下:

編過(guò)碼的響應(yīng)內(nèi)容:

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25

這是第一段數(shù)據(jù)

1A

然后這是第二段數(shù)據(jù)

0

解碼的數(shù)據(jù):

這是第一段內(nèi)容,然后這是第二段數(shù)據(jù)

情況搞清楚了,那么我們?cè)趺磥?lái)解碼這個(gè)編碼后的數(shù)據(jù)呢?

在php官方手冊(cè)fsockopen函數(shù)下面的評(píng)論中,已經(jīng)有很多人提出了解決方法

方法1.

<?phpfunction unchunk($result) {return preg_replace_callback('/(?:(?:/r/n|/n)|^)([0-9A-F]+)(?:/r/n|/n){1,2}(.*?)'.'((?:/r/n|/n)(?:[0-9A-F]+(?:/r/n|/n))|$)/si',create_function('$matches','return hexdec($matches[1]) == strlen($matches[2]) ? $matches[2] : $matches[0];'),$result);}

方法二.

function unchunkHttp11($data) {$fp = 0;$outData = "";while ($fp < strlen($data)) {$rawnum = substr($data, $fp, strpos(substr($data, $fp), "/r/n") + 2);$num = hexdec(trim($rawnum));$fp += strlen($rawnum);$chunk = substr($data, $fp, $num);$outData .= $chunk;$fp += strlen($chunk);}return $outData;}

注意:這兩個(gè)函數(shù)的參數(shù)都是返回的http原始數(shù)據(jù)(包括頭)



注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到PHP教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 徐汇区| 南江县| 卢龙县| 阿坝县| 利津县| 麻城市| 孟村| 华亭县| 新巴尔虎右旗| 巩义市| 齐齐哈尔市| 潍坊市| 卫辉市| 蒲江县| 安庆市| 北京市| 白城市| 铜鼓县| 始兴县| 马龙县| 宜州市| 麟游县| 来宾市| 正蓝旗| 平山县| 惠来县| 万荣县| 荃湾区| 武平县| 常宁市| 连平县| 美姑县| 曲水县| 明水县| 通化县| 永和县| 大渡口区| 江达县| 孟连| 方城县| 都兰县|