1 Star 0 Fork 344

PHP开发者联盟 / swoole-src

forked from swoole / swoole-src 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

Swoole

Build Status License Join the chat at https://gitter.im/swoole/swoole-src Coverity Scan Build Status

Swoole is an event-driven asynchronous & concurrent networking communication framework with high performance written only in C for PHP.

Swoft

Modern High performance AOP and Coroutine PHP Framework, base on Swoole 2 https://github.com/swoft-cloud

EasySwoole

a simple high performance PHP framework base on Swoole which make you use Swoole like echo hello world。https://www.easyswoole.com/

SwooleDistributed

The high performance co operative server framework base on swoole all version, supports microservice and cluster deployment, providing developers with many advanced development and debugging components. https://github.com/SwooleDistributed/SwooleDistributed

Event-based

The network layer in Swoole is event-based and takes full advantage of the underlaying epoll/kqueue implementation, making it really easy to serve thousands of connections.

Coroutine

Swoole 2.0 supports the built-in coroutine, and you can use fully synchronized code to implement asynchronous programs. PHP code without any additional keywords, the underlying automatic coroutine-scheduling.

<?php
for ($i = 0; $i < 100; $i++) {
    Swoole\Coroutine::create(function() use ($i) {
        $redis = new Swoole\Coroutine\Redis();
        $res = $redis->connect('127.0.0.1', 6379);
        $ret = $redis->incr('coroutine');
        $redis->close();
        if ($i == 50) {
            Swoole\Coroutine::create(function() use ($i) {
                $redis = new Swoole\Coroutine\Redis();
                $res = $redis->connect('127.0.0.1', 6379);
                $ret = $redis->set('coroutine_i', 50);
                $redis->close();
            });
        }
    });
}
<?php
$server = new Swoole\Http\Server('127.0.0.1', 9501);

$server->on('Request', function($request, $response) {

    $tcp_cli = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
    $ret = $tcp_cli->connect('127.0.0.1', 9906);
    $tcp_cli ->send('test for the coroutine');
    $ret = $tcp_cli->recv(5);
    $tcp_cli->close();

    if ($ret) {
        $response->end(' swoole response is ok');
    }
    else{
        $response->end(" recv failed error : {$client->errCode}");
    }
});

$server->start();

Short API Name

start a new coroutine

go(function () {
    co::sleep(0.5);
    echo "hello";
});
go("test");
go([$object, "method"]);

Channel

$chan = new chan(128);
$chan->push(1234);
$chan->push(1234.56);
$chan->push("hello world");
$chan->push(["hello world"]);
$chan->push(new stdclass);
$chan->push(fopen("test.txt", "r+"));
while($chan->pop());

MySQL Client

go(function () {
    $db = new Co\MySQL();
    $server = array(
        'host' => '127.0.0.1',
        'user' => 'root',
        'password' => 'root',
        'database' => 'test',
    );

    $db->connect($server);

    $result = $db->query('SELECT * FROM userinfo WHERE id = 3');
    var_dump($result);
});

Redis Client

go(function () {
    $redis = new Co\Redis;
    $res = $redis->connect('127.0.0.1', 6379);
    $ret = $redis->set('key', 'value');
    var_dump($redis->get('key'));
});

Http Client

go(function () {
    $http = new Co\Http\Client("www.google.com", 443, true);
    $http->setHeaders(function () {
        
    });
    $ret = $http->get('/');
    var_dump($http->body);
});

Http2 Client

go(function () {
    $http = new Co\Http2\Client("www.google.com", 443, true);
    $req = new co\Http2\Request;
    $req->path = "/index.html";
    $req->headers = [
        'host' => "www.google.com",
        "user-agent" => 'Chrome/49.0.2587.3',
        'accept' => 'text/html,application/xhtml+xml,application/xml',
        'accept-encoding' => 'gzip',
    ];
    $req->cookies = ['name' => 'rango', 'email' => 'rango@swoole.com'];
    $ret = $http->send($req);
    var_dump($http->recv());
});

Other

co::sleep(100);
co::fread($fp);
co::gethostbyname('www.google.com');

Concurrent

On the request processing part, Swoole uses a multi-process model. Every process works as a worker. All business logic is executed in workers, synchronously.

With the synchronous logic execution, you can easily write large and robust applications and take advantage of almost all libraries available to the PHP community.

In-memory

Unlike traditional apache/php-fpm stuff, the memory allocated in Swoole will not be freed after a request, which can improve performance a lot.

Why Swoole?

Traditional PHP applications almost always run behind Apache/Nginx, without much control of the request. This brings several limitations:

  1. All memory will be freed after the request. All PHP code needs be re-compiled on every request. Even with opcache enabled, all opcode still needs to be re-executed.
  2. It is almost impossible to implement long connections and connection pooling techniques.
  3. Implementing asynchronous tasks requires third-party queue servers, such as rabbitmq and beanstalkd.
  4. Implementing realtime applications such as chatting servers requires third-party languages, such as nodejs, for example.

This is why Swoole appeared. Swoole extends the use cases of PHP, and brings all these possibilities to the PHP world. By using Swoole, you can build enhanced web applications with more control, real-time chatting servers, etc, more easily.

Requirements

  • Version-1: PHP 5.3.10 or later
  • Version-2: PHP 5.5.0 or later
  • Linux, OS X and basic Windows support (thanks to cygwin)
  • GCC 4.4 or later

Installation

  1. Install via pecl

    pecl install swoole
  2. Install from source

    sudo apt-get install php5-dev
    git clone https://github.com/swoole/swoole-src.git
    cd swoole-src
    phpize
    ./configure
    make && make install

Introduction

Swoole includes components for different purposes: Server, Task Worker, Timer, Event and Async IO. With these components, Swoole allows you to build many features.

Server

This is the most important part in Swoole. It provides the necessary infrastructure to build server applications. With Swoole server, you can build web servers, chat messaging servers, game servers and almost anything you want.

The following example shows a simple echo server.

// Create a server instance
$serv = new swoole_server('127.0.0.1', 9501);

// Attach handler for connect event. Once the client has connected to the server, the registered handler will be
// executed.
$serv->on('connect', function ($serv, $fd) {
    echo "Client:Connect.\n";
});

// Attach handler for receive event. Every piece of data will be received by server and the registered handler will be
// executed. All custom protocol implementation should be located there.
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
    $serv->send($fd, $data);
});

$serv->on('close', function ($serv, $fd) {
    echo "Client: Close.\n";
});

// Start our server, listen on the port and be ready to accept connections.
$serv->start();

Try to extend your server and implement what you want!

HTTP Server

$http = new swoole_http_server('0.0.0.0', 9501);

$http->on('request', function ($request, $response) {
    $response->header('Content-Type', 'text/html; charset=utf-8');
    $response->end('<h1>Hello Swoole. #' . rand(1000, 9999) . '</h1>');
});

$http->start();

WebSocket Server

$ws = new swoole_websocket_server('0.0.0.0', 9502);

$ws->on('open', function ($ws, $request) {
    var_dump($request->fd, $request->get, $request->server);
    $ws->push($request->fd, "hello, welcome\n");
});

$ws->on('message', function ($ws, $frame) {
    echo "Message: {$frame->data}\n";
    $ws->push($frame->fd, "server: {$frame->data}");
});

$ws->on('close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});

$ws->start();

Real async-mysql client

$db = new swoole_mysql('127.0.0.1', 'root', 'root', 'test');

$db->on('close', function($o) {
    echo "mysql connection is closed\n";
});

$db->query('select now() as now_t', function($db, $result_rows) {
    var_dump($result_rows);
    $db->close();
});

Real async-redis client

$client = new swoole_redis;
$client->connect('127.0.0.1', 6379, function (swoole_redis $client, $result) {
    echo "connect\n";
    var_dump($result);
    $client->set('key', 'swoole', function (swoole_redis $client, $result) {
        var_dump($result);
        $client->get('key', function (swoole_redis $client, $result) {
            var_dump($result);
            $client->close();
        });
    });
});

Async http Client

$cli = new swoole_http_client('127.0.0.1', 80);

$cli->setHeaders(['User-Agent' => 'swoole']);
$cli->post('/dump.php', array('test' => '9999999'), function (swoole_http_client $cli) {
    echo "#{$cli->sock}\tPOST response Length: " . strlen($cli->body) . "\n";
    $cli->get('/index.php', function (swoole_http_client $cli) {
        echo "#{$cli->sock}\tGET response Length: " . strlen($cli->body) . "\n";
    });
});

Async WebSocket Client

$cli = new swoole_http_client('127.0.0.1', 9501);

$cli->on('message', function ($_cli, $frame) {
    var_dump($frame);
});

$cli->upgrade('/', function ($cli) {
    echo $cli->body;
    $cli->push('Hello world');
});

Multi-port and mixed protocol

$serv = new swoole_http_server('127.0.0.1', 9501, SWOOLE_BASE);

$port2 = $serv->listen('0.0.0.0', 9502, SWOOLE_SOCK_TCP);
$port2->on('receive', function (swoole_server $serv, $fd, $from_id, $data) {
    var_dump($data);
    $serv->send($fd, $data);
});

$serv->on('request', function($req, $resp) {
    $resp->end('<h1>Hello world</h1>');
});


$serv->start();

Task Worker

Swoole brings you two types of workers: server workers and task workers. Server workers are for request handling, as demonstrated above. Task workers are for task execution. With task workers, we can execute our task asynchronously without blocking the server workers.

Task workers are mainly used for time-consuming tasks, such as sending password recovery emails, and ensure the main request returns as soon as possible.

The following example shows a simple server with task support.

$serv = new swoole_server("127.0.0.1", 9502);

// Sets server configuration, we set task_worker_num config greater than 0 to enable task workers support
$serv->set(array('task_worker_num' => 4));

// Attach handler for receive event, which has been explained above.
$serv->on('receive', function($serv, $fd, $from_id, $data) {
    // We dispath a task to task workers by invoke the task() method of $serv
    // This method returns a task id as the identity of ths task
    $task_id = $serv->task($data);
    echo "Dispath AsyncTask: id=$task_id\n";
});

// Attach handler for task event. The handler will be executed in task workers.
$serv->on('task', function ($serv, $task_id, $from_id, $data) {
    // Handle the task and do what you want with $data
    echo "New AsyncTask[id=$task_id]" . PHP_EOL;

    // After the task is handled, we return the results to the caller worker.
    $serv->finish("$data -> OK");
});

// Attach handler for finish event. The handler will be executed in server workers. The same worker dispatched this task before.
$serv->on('finish', function ($serv, $task_id, $data) {
    echo "AsyncTask[$task_id] Finish: $data" . PHP_EOL;
});

$serv->start();

Swoole also supports synchronous tasks. To use synchronous tasks, just simply replace $serv->task($data) with $serv->taskwait($data). Unlike task(), taskwait() will wait for a task to complete before it returns its response.

Timer

Swoole has built-in millisecond timer support. By using the timer, it is easy to get a block of code executed periodically (really useful for managing interval tasks).

To demonstrate how the timer works, here is a small example:

//interval 2000ms
$serv->tick(2000, function ($timer_id) {
    echo "tick-2000ms\n";
});

//after 3000ms
$serv->after(3000, function () {
    echo "after 3000ms.\n"
});

In the example above, we first set the timer event handler to swoole_server to enable timer support. Then, we add two timers by calling bool swoole_server::addtimer($interval) once the server started. To handle multiple timers, we switch the $interval in registered handler and do what we want to do.

Event

Swoole's I/O layer is event-based, which is very convenient to add your own file descriptor to Swoole's main eventloop. With event support, you can also build fully asynchronous applications with Swoole.

To use events in Swoole, we can use swoole_event_set() to register event handler to sepecified file descriptor, once registered descriptors become readable or writeable, our registered handler will be invoked. Also, we can using bool swoole_event_del(int $fd); to remove registered file descriptor from eventloop.

The following are prototypes for the related functions:

bool swoole_event_add($fd, mixed $read_callback, mixed $write_callback, int $flag);
bool swoole_event_set($fd, mixed $read_callback, mixed $write_callback, int $flag);
bool swoole_event_del($fd);

The $fd parameter can be one of the following types:

  • unix file descriptor
  • stream resource created by stream_socket_client()/fsockopen()
  • sockets resources created by socket_create() in sockets extension (require compile swoole with --enable-sockets support)

The $read_callback and $write_callback are callbacks for corresponding read/write event.

The $flag is a mask to indicate what type of events we should get notified, can be SWOOLE_EVENT_READ, SWOOLE_EVENT_WRITE or SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE

Async IO

Swoole's Async IO provides the ability to read/write files and lookup dns records asynchronously. The following are signatures for these functions:

bool swoole_async_readfile(string $filename, mixed $callback);
bool swoole_async_writefile('test.log', $file_content, mixed $callback);
bool swoole_async_read(string $filename, mixed $callback, int $trunk_size = 8192);
bool swoole_async_write(string $filename, string $content, int $offset = -1, mixed $callback = NULL);
void swoole_async_dns_lookup(string $domain, function($host, $ip){});
bool swoole_timer_after($after_n_ms, mixed $callback);
bool swoole_timer_tick($n_ms, mixed $callback);
bool swoole_timer_clear($n_ms, mixed $callback);

Refer to API Reference for more detailed information about these functions.

Client

Swoole also provides a client component to build tcp/udp clients in both asynchronous and synchronous ways. Swoole uses the swoole_client class to expose all its functionalities.

synchronous blocking:

$client = new swoole_client(SWOOLE_SOCK_TCP);
if (!$client->connect('127.0.0.1', 9501, 0.5)) {
    die('connect failed.');
}

if (!$client->send('Hello world')) {
    die('send failed.');
}

$data = $client->recv();
if (!$data) {
    die('recv failed.');
}

$client->close();

Asynchronous non-blocking:

$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);

$client->on('connect', function($cli) {
    $cli->send("Hello world\n");
});
$client->on('receive', function($cli, $data) {
    echo "Received: ".$data."\n";
});
$client->on('error', function($cli) {
    echo "Connect failed\n";
});
$client->on('close', function($cli) {
    echo "Connection close\n";
});

$client->connect('127.0.0.1', 9501, 0.5);

The following methods are available in swoole_client:

swoole_client::__construct(int $sock_type, int $is_sync = SWOOLE_SOCK_SYNC, string $key);
int swoole_client::on(string $event, mixed $callback);
bool swoole_client::connect(string $host, int $port, float $timeout = 0.1, int $flag = 0)
bool swoole_client::isConnected();
int swoole_client::send(string $data);
bool swoole_client::sendfile(string $filename)
string swoole_client::recv(int $size = 65535, bool $waitall = 0);
bool swoole_client::close();

Refer to API Reference for more detailed information about these functions.

API Reference

Related Projects

Contribution

Your contribution to Swoole development is very welcome!

You may contribute in the following ways:

License

Apache License Version 2.0 see http://www.apache.org/licenses/LICENSE-2.0.html

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright Tianfeng.Han [mikan.tenny@gmail.com] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

PHP的异步、并行、高性能网络通信引擎 展开 收起
C
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
C
1
https://gitee.com/FunTeam/swoole.git
git@gitee.com:FunTeam/swoole.git
FunTeam
swoole
swoole-src
master

搜索帮助

14c37bed 8189591 565d56ea 8189591