php_http_parser 正在参加 2020 年度 OSC 中国开源项目评选,请投票支持!
php_http_parser 在 2020 年度 OSC 中国开源项目评选 中已获得 {{ projectVoteCount }} 票,请投票支持!
投票让它出道
已投票
php_http_parser 获得 2020 年度 OSC 中国开源项目评选「最佳人气项目」 !
php_http_parser 获得 2020 年度 OSC 中国开源项目评选「最佳人气项目」「最积极运营项目」 !
php_http_parser 获得 2020 年度 OSC 中国开源项目评选「最积极运营项目」 !
授权协议 MIT
开发语言 PHP
操作系统 跨平台
软件类型 开源软件
所属分类 程序开发网络工具包
开发厂商
地区 国产
提 交 者 coooold
适用人群 未知
收录时间 2015-11-18

软件简介

php_http_parser 是基于node.js http-parser的PHP扩展,可用于实现纯异步PHP程序

libcurl提供了异步调用方式,有两种风格:

  • ONE MULTI HANDLE MANY EASY HANDLES:加入多个easy handle后执行curl_multi_perform方法。该方法在php curl扩展中有对应实现。但最后一步curl_multi_perform是阻塞的。

  • MULTI_SOCKET,这个是真正的非阻塞方法,但需要自行实现event loop,且封装较为困难,目前在php中没有对应实现。经过调研,curl_multi_socket_action跟php内核结合困难度很高。

除此之外,基本上没有真正的实现异步http请求的php扩展。目前仅有部分纯php实现的版本,比如tsf中的http client实现。 使用纯php实现的问题主要受限于http解析的性能。因此考虑将这一模块用扩展的方式来实现。node.js http-parser就是一个很好的c语言的http解析库。 php_http_parser就是对其做的一个封装,在php中暴露出相应的接口。

为了实现真正的非阻塞请求,仍然需要自己实现event loop。目前推荐结合swoole使用,以获得更好的性能。

使用方式

$buffs = array("HTTP/1.1 301 Moved Permanently\r\n"
,"Location: http://www.google.com/\r\n"
,"Content-Type: text/html; charset=UTF-8\r\n"
,"Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n"
,"Expires: Tue, 26 May 2009 11:11:49 GMT\r\n"
,"Cache-Control: public, max-age=2592000\r\n"
,"Server: gws\r\n"
,"Content-Length: 193\r\n"
,"\r\n"
,"<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"
,"<TITLE>301 Moved</TITLE></HEAD><BODY>\n"
,"<H1>301 Moved</H1>\n"
,"The document has moved\n"
,"<A HREF=\"http://www.google.com/\">here</A>.\r\n"
    ,"<A HREF=\"http://www.google.com/\">here</A>.\r\n"
    ,"<A HREF=\"http://www.google.com/\">here</A>.\r\n"
    ,"<A HREF=\"http://www.google.com/\">here</A>.\r\n"
    ,"<A HREF=\"http://www.google.com/\">here</A>.\r\n"
,"</BODY></HTML>\r\n");
$hp = new HttpParser();
foreach($buffs as $buff){
    $ret = $hp->execute($buff);
    if($ret !== false){
        echo $ret;
        break;
    }
}

虽然http请求可能分包发送,HttpParser会将所有包合并在一起后,出发body事件,然后调用相应的回调方法。 诸如header回调,目前暂未实现。另外,此处需要自行实现timeout逻辑。

示例代码是结合swoole_client与swPromise框架实现的一个异步http client。 籍此可以实现真正的非阻塞的PHP程序。

class HttpClientFuture implements FutureIntf {
    protected $url = null;
    protected $post = null;
    protected $proxy = false;
    public function __construct($url, $post = array(), $proxy = array()) {
        $this->url = $url;
        $this->post = $post;
        if($proxy){
            $this->proxy = $proxy;
        }
    }
    public function run(Promise &$promise) {
        $cli = new \swoole_client ( SWOOLE_TCP, SWOOLE_SOCK_ASYNC );
        $urlInfo = parse_url ( $this->url );
        if(!isset($urlInfo ['port']))$urlInfo ['port'] = 80;
        $httpParser = new \HttpParser();
        $cli->on ( "connect", function ($cli)use($urlInfo){
            $host = $urlInfo['host'];
            if($urlInfo['port'])$host .= ':'.$urlInfo['port'];
            $req = array();
            $req[] = "GET {$this->url} HTTP/1.1\r\n";
            $req[] = "User-Agent: PHP swAsync\r\n";
            $req[] = "Host:{$host}\r\n";
            $req[] = "Connection:close\r\n";
            $req[] = "\r\n";
            $req = implode('', $req);
            $cli->send ( $req );
        } );
        $cli->on ( "receive", function ($cli, $data = "") use(&$httpParser, &$promise) {
            $ret = $httpParser->execute($data);
            if($ret !== false){
                $cli->close();
                $promise->accept(['http_data'=>$ret]);
            }
        } );
        $cli->on ( "error", function ($cli) use(&$promise) {
            $promise->reject ();
        } );
        $cli->on ( "close", function ($cli) {
        } );
        if($this->proxy){
            $cli->connect ( $this->proxy['host'], $this->proxy ['port'], 1 );
        }else{
            $cli->connect ( $urlInfo ['host'], $urlInfo ['port'], 1 );
        }
    }
}

性能

[web@gz-web01 php_http_parser]$ time /data/server/php/bin/php http_parser.php  2000000

real    0m11.489s
user    0m11.435s
sys 0m0.017s

1个worker进程

./http_load -fetches 20000 -parallel 100 9502.listasync 
20000 fetches, 100 max parallel, 2.02e+06 bytes, in 5.94536 seconds
101 mean bytes/connection
3363.97 fetches/sec, 339761 bytes/sec
msecs/connect: 0.0473873 mean, 1.155 max, 0.019 min
msecs/first-response: 29.6366 mean, 51.736 max, 15.22 min
HTTP response codes:
code 200 -- 20000
-bash: history: write error: Success

2个worker进程

./http_load -fetches 20000 -parallel 100 9502.listasync 
20000 fetches, 100 max parallel, 2.02e+06 bytes, in 3.17119 seconds
101 mean bytes/connection
6306.77 fetches/sec, 636984 bytes/sec
msecs/connect: 0.0643583 mean, 1.211 max, 0.023 min
msecs/first-response: 15.7489 mean, 32.425 max, 3.242 min
HTTP response codes:
code 200 -- 20000
-bash: history: write error: Success

4个woker进程

./http_load -fetches 20000 -parallel 100 9502.listasync 
20000 fetches, 100 max parallel, 2.02e+06 bytes, in 1.57194 seconds
101 mean bytes/connection
12723.2 fetches/sec, 1.28504e+06 bytes/sec
msecs/connect: 0.0815263 mean, 1.349 max, 0.02 min
msecs/first-response: 7.65904 mean, 22.568 max, 1.221 min
HTTP response codes:
code 200 -- 20000
-bash: history: write error: Success

8个woker进程

./http_load -fetches 20000 -parallel 100 9502.listasync 
20000 fetches, 100 max parallel, 2.02e+06 bytes, in 1.02967 seconds
101 mean bytes/connection
19423.8 fetches/sec, 1.9618e+06 bytes/sec
msecs/connect: 0.147502 mean, 1.575 max, 0.014 min
msecs/first-response: 3.17218 mean, 22.566 max, 0.339 min
HTTP response codes:
code 200 -- 20000
-bash: history: write error: Success
展开阅读全文

代码

的 Gitee 指数为
超过 的项目

评论 (0)

加载中
更多评论
暂无内容
发表了博客
2020/07/27 14:22

开源HTTP解析器---http-parser和fast-http

由于项目中遇到需要发送http请求,然后再解析接收到的响应。大概在网上搜索了一下,有两个比较不错,分别是http-parser和fast-http。 http-parser是由C编写的工具;fast-http是大部分移植自http-parser,用lisp语言编写的,不太适合目前的项目。fast-http介绍文档《fast-http》。 有一篇文章《HTTP 协议解析库:fast-ht...

0
0
发表了博客
2020/07/29 07:20

开源HTTP解析器---http-parser和fast-http

由于项目中遇到需要发送http请求,然后再解析接收到的响应。大概在网上搜索了一下,有两个比较不错,分别是http-parser和fast-http。 http-parser是由C编写的工具;fast-http是大部分移植自http-parser,用lisp语言编写的,不太适合目前的项目。fast-http介绍文档《fast-http》。 有一篇文章《HTTP 协议解析库:fast-ht...

0
0
2016/11/22 09:11

PHP xml_parser函数

定义和用法 xml_parser_set_option() 函数为 XML 解析器进行选项设置。 如果成功,则返回 true。如果失败,则返回 false。 语法 xml_parser_set_option(parser,option,value) 参数 描述 parser 必需。规定要使用的 XML 解析器。 option 必需。规定要设置的设置选项名称。可能的值: XML_OPTION_CASE_FOLDING XML_OPTION...

0
0
发表了博客
2019/01/10 11:09

PHP Cron Expression Parser ( LARAVEL )

The PHP cron expression parser can parse a CRON expression, determine if it is due to run, calculate the next run date of the expression, and calculate the previous run date of the expression. You can calculate dates far into the future or past by skipping n number of matching dates. The parser c...

0
0
发表了博客
2019/04/04 14:22

php-parser在Aop编程中的使用

在laravel下使用php-parser实现aop composer require nikic/php-parser Test.php <?php /** * Created by PhpStorm. * User: CSH * Date: 2019/4/4 * Time: 11:26 */ namespace app; /** * 为该类创建代理,并植入切面 埋点 * 使用parser生成对应的语法树,然后主动修改方法体内的逻辑 * * Class Test * @p...

0
0
发表了博客
2013/07/09 14:24

RSS_PHP - the PHP DOM based RSS Parser

<?php /*   RSS_PHP - the PHP DOM based RSS Parser   Author: <rssphp.net>   Published: 200801 :: blacknet :: via rssphp.net      RSS_PHP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.   Usage:     See the documentation at http://rssphp.net/documentation   Examples: ...

0
0
发表了博客
2020/01/09 14:52

nikic / PHP-Parser 包的简单实用

解析PHP文件: <?php require 'vendor/autoload.php'; use PhpParser\ParserFactory; $code = file_get_contents(dirname(__FILE__) . '/src/Aop/Target.php'); $phpFactory = new ParserFactory(); $parser = $phpFactory->create(ParserFactory::PREFER_PHP7); //var_dump($parser->parse($code));die(); foreach ...

0
0
发表了博客
2019/03/12 14:28

GCC 7.3.0版本编译http-parser-2.1问题

http-paser是一个用c编写的http消息解析器,地址:https://github.com/nodejs/http-parser,目前版本2.9 今天用gcc 7.3.0编译其2.1版本时,编译器报错如下: 找到对应的代码: http-parser的编译同时打开了-Wall -Wextra -Werror -Wimplicit-fallthrough,是C++17标准引入的警告选项,因为这个地方没有break。如果编译时...

0
0
发表了博客
2013/05/07 22:57

关于PHP Simple HTML DOM Parser的异常处理

1.关于PHP Simple HTML DOM Parser加载大页面报错 加载大页面(比如:http://www.ebates.com/stores/all/index.htm)时,你调用其中的find的方法,报的错误信息是:Get Cssh back!PHP Fatal error: Call to a member function find() on a non-object,原因是你调用file_get_html($url);将永远返回false,因为它限制最大的...

0
4
发表了博客
2013/05/08 15:42

PHP - HTTP_REFERER

看UCHome和ECShop源码的时候,发现经常会用到$_SERVER['HTTP_REFERER']的值。HTTP REFERER是Header的一部分,当浏览器向WEB服务器发送请求的时候,一般会带上HTTP REFERER,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里,他的服务器就能够从 HTTP REFER...

0
0
没有更多内容
加载失败,请刷新页面
点击加载更多
加载中
下一页
暂无内容
0 评论
15 收藏
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部