Init Repo

This commit is contained in:
root
2019-09-06 23:53:10 +08:00
commit f0ef89dfbb
7905 changed files with 914138 additions and 0 deletions

View File

@ -0,0 +1,86 @@
<?php
$http = new swoole_http_server("127.0.0.1", 9501, SWOOLE_BASE);
$http->set(array(
'log_file' => '/dev/null',
"http_parse_post" => 1,
"upload_tmp_dir" => "/tmp",
));
$http->on("WorkerStart", function (\swoole_server $serv)
{
/**
* @var $pm ProcessManager
*/
global $pm;
if ($pm)
{
$pm->wakeup();
}
});
$http->on('request', function ($request, swoole_http_response $response)
{
$route = $request->server['request_uri'];
if ($route == '/info')
{
$response->end($request->header['user-agent']);
return;
}
elseif ($route == '/cookies')
{
$response->end(@json_encode($request->cookie));
return;
}
elseif ($route == '/get')
{
$response->end(@json_encode($request->get));
return;
}
elseif ($route == '/post')
{
$response->end(@json_encode($request->post));
return;
}
elseif ($route == '/get_file')
{
$response->sendfile(TEST_IMAGE);
return;
}
elseif ($route == '/upload_file')
{
$response->end(json_encode([
'files' => $request->files,
'md5' => md5_file($request->files['test_jpg']['tmp_name']),
'post' => $request->post
]));
return;
}
elseif ($route == '/gzip')
{
$response->gzip(5);
Swoole\Async::readFile(__DIR__ . '/../../../README.md', function ($file, $content) use ($response) {
$response->end($content);
});
return;
}
else
{
$cli = new swoole_http_client('127.0.0.1', 9501);
$cli->set(array(
'timeout' => 0.3,
));
$cli->setHeaders(array('User-Agent' => "swoole"));
$cli->on('close', function ($cli) use ($response)
{
});
$cli->on('error', function ($cli) use ($response)
{
echo "error";
$response->end("error");
});
$cli->get('/info', function ($cli) use ($response)
{
$response->end($cli->body . "\n");
$cli->close();
});
}
});
$http->start();

View File

@ -0,0 +1,175 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
// TODO 线上版本 512k coredump
//$chunk = 1024 * 512;
//parallel_read_copy($chunk);
//$chunk = 1024 * 1024;
//parallel_read_copy($chunk);
//$chunk = 1024 * 1024 - 1;
//parallel_read_copy($chunk);
//serial_read_copy();
// DOC
// 读全部文件chunk = -1 或者 不传递
// 不需要chunk参数强制性一次读取1M数据
// swoole_function swoole_async_read($file, callable $cb, $chunk, $offset) {}
// 新接口取消readfile与writefile
function gen_rand_file($file, $m = 10)
{
// !! linux 的bs不支持m作为单位 !!!
$bs = 1024 * 1024;
`dd if=/dev/urandom of=$file bs=$bs count=$m >/dev/null 2>&1`;
// 可能会失败
// return filesize($file);
return $m * 1024 * 1024;
}
// 验证复制完整性并清理文件
function valid_clean($from, $to)
{
// echo "copy finished\n";
// echo `ls -alh | grep $from`;
$diff = `diff $from $to`; // valid
if ($diff) {
echo $diff;
echo "FAIL\n";
} else {
echo "SUCCESS\n";
}
@unlink($from);
@unlink($to);
}
// 重构后swoole版本api
function serial_read_copy($size_m = 10)
{
$start = microtime(true);
$chunk = 1024 * 1024;
$offset = 0;
$file = "bigfile";
$origin_size = gen_rand_file($file, $size_m);
$n = (int)ceil($origin_size / $chunk);
swoole_async_set([ "thread_num" => $n,]);
$i = 0;
swoole_async_read($file, function($filename, $content) use($file, &$offset, &$n, &$i, $start) {
$read_size = strlen($content);
//echo "<$i> read [offset=$offset, len=$read_size]\n";
$continue = $read_size !== 0;
if ($continue) {
swoole_async_write("$file.copy", $content, $offset, function($write_file, $write_size) use($file, $offset, $read_size, &$n, $i, $start) {
$n--;
assert($read_size === $write_size); // 断言分块全部写入
//echo "<$i> write [offset=$offset, len=$write_size]\n";
if ($n === 0) {
//echo "cost: ", microtime(true) - $start, "\n";
valid_clean($file, $write_file);
}
});
}
$offset += $read_size;
$i++;
return $continue;
}, $chunk);
}
function parallel_read_copy($chunk, $size_m = 10)
{
$start = microtime(true);
$offset = 0;
$file = "bigfile";
//生成一个10M大小的文件
$origin_size = gen_rand_file($file, $size_m);
$n = (int)ceil($origin_size / $chunk);
//设置线程数
swoole_async_set([ "thread_num" => $n,]);
for ($i = 0; $i < $n; $i++) {
$offset = $i * $chunk;
swoole_async_read($file, function($filename, $content) use($file, $offset, $i, &$n, $start) {
$read_size = strlen($content);
// echo "<$i> read [offset=$offset, len=$read_size]\n";
swoole_async_write("$file.copy", $content, $offset, function($write_file, $write_size) use($file, $offset, $read_size, &$n, $i, $start) {
$n--;
assert($read_size === $write_size); // 断言分块全部写入
// echo "<$i> write [offset=$offset, len=$write_size]\n";
if ($n === 0) {
// echo "cost: ", microtime(true) - $start, "\n";
valid_clean($file, $write_file);
}
});
// !!! 只读取单独chunk停止继续读
return false;
}, $chunk, $offset);
}
}
// 旧的swoole版本api 使用
function serial_copy_old($chunk)
{
$offset = 0;
$file = "bigfile";
$origin_size = gen_rand_file($file);
$n = (int)ceil($origin_size / $chunk);
swoole_async_set([ "thread_num" => $n,]);
$i = 0;
swoole_async_read($file, function($filename, $content) use($file, &$offset, &$n, &$i) {
$read_size = strlen($content);
echo "<$i> read [offset=$offset, len=$read_size]\n";
$continue = $read_size !== 0;
if ($continue) {
swoole_async_write("$file.copy", $content, $offset, function($write_file, $write_size) use($file, $offset, $read_size, &$n, $i) {
$n--;
assert($read_size === $write_size); // 断言分块全部写入
echo "<$i> write [offset=$offset, len=$write_size]\n";
if ($n === 0) {
valid_clean($file, $write_file);
}
});
}
$offset += $read_size;
$i++;
return $continue;
}, $chunk);
}

View File

@ -0,0 +1,54 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//$file = __DIR__ . "/tmp.file";
// 最大 限制1024M
// user set data swoole_buffer must between 0~1048576
//$data = file_get_contents("/dev/urandom", null, null, null, 1024 * 1024 + 1);
//swoole_async_write($file, $data, -1, swoole_function($f, $l) {
// var_dump($l);
//});
//@unlink($file);
/*
$recursiveWrite = swoole_function($dep = 0) use($data, &$recursiveWrite, $file, $size) {
swoole_async_write($file, $data, -1, swoole_function ($file, $len) use(&$recursiveWrite, $dep, $size) {
if ($dep > 100) {
echo "SUCCESS";
unlink($file);
return false;
}
assert($len === $size);
$recursiveWrite(++$dep);
return true;
});
};
*/
// $recursiveWrite();
function recursiveWrite($dep = 0, $size = 1024 * 1024)
{
static $data;
if ($data === null) {
$data = file_get_contents("/dev/urandom", null, null, null, $size);
}
$file = "tmp.file";
swoole_async_write($file, $data, -1, function ($file, $len) use(&$recursiveWrite, $dep, $size) {
if ($dep > 100) {
echo "SUCCESS";
unlink($file);
return false;
}
assert($len === $size);
recursiveWrite(++$dep);
return true;
});
}

View File

@ -0,0 +1,66 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//swoole_function swoole_async_read($filename, $callback, $chunk_size = null, $offset = null) {}
function read_dev_zero()
{
$context = file_get_contents("/dev/zero", null, null, null, 8192);
assert(strlen($context) === 8192);
// TODO WARNING zif_swoole_async_read: offset must be less than file_size[=0].
swoole_async_read("/dev/zero", function ($filename, $content) {
echo "file: $filename\ncontent-length: " . strlen($content) . "\nContent: $content\n";
if (empty($content)) {
echo "file is end.\n";
return false;
} else {
return true;
}
}, 8192);
}
function read_dev_null()
{
$context = file_get_contents("/dev/null", null, null, null, 8192);
assert(strlen($context) === 0);
// TODO WARNING zif_swoole_async_read: offset must be less than file_size[=0].
swoole_async_read("/dev/null", function ($filename, $content) {
echo "file: $filename\ncontent-length: " . strlen($content) . "\nContent: $content\n";
if (empty($content)) {
echo "file is end.\n";
return false;
} else {
return true;
}
}, 8192);
}
function read_normal_file()
{
$context = file_get_contents(__FILE__, null, null, null, 8192);
$len = strlen($context);
swoole_async_read(__FILE__, function ($filename, $content) use($len) {
echo "read callback\n";
// echo $len, "\n";
// echo strlen($content), "\n";
// assert($len === strlen($content));
if (empty($content)) {
echo "file is end.\n";
return false;
} else {
return true;
}
}, 8192);
}
read_dev_zero();
read_dev_null();
read_normal_file();
// todo read 大文件

View File

@ -0,0 +1,67 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//swoole_function swoole_async_write($filename, $content, $offset = null, $callback = null) {}
//callback: return true: write contine. return false: close the file.
function write_dev_zero()
{
$data = str_repeat("\0", 8192);
$len = file_put_contents("/dev/zero", $data);
assert($len === 8192);
for ($i = 0; $i < 100; $i++) {
swoole_async_write("/dev/zero", $data, -1, function ($file, $len) {
echo "write /dev/zero $len size\n";
return true;
});
}
}
function write_dev_null()
{
$data = str_repeat("\0", 8192);
$len = file_put_contents("/dev/null", $data);
assert($len === 8192);
for ($i = 0; $i < 100; $i++) {
swoole_async_write("/dev/null", $data, -1, function ($file, $len) {
echo "write /dev/null $len size\n";
return true;
});
}
}
function write_normal_file()
{
$file = __DIR__ . "/zero";
$data = str_repeat("\0", 8192);
$len = file_put_contents($file, $data);
assert($len === 8192);
unlink($file);
/** @noinspection PhpUnusedLocalVariableInspection
* @param int $dep
*/
$recursiveWrite = function($dep = 0) use($data, &$recursiveWrite, $file) {
swoole_async_write($file, $data, -1, function ($file, $len) use(&$recursiveWrite, $dep) {
if ($dep > 100) {
unlink($file);
return false;
}
echo "write $file $len size\n";
$recursiveWrite(++$dep);
return true;
});
};
$recursiveWrite();
}
write_dev_zero();
write_dev_null();
write_normal_file();

View File

@ -0,0 +1,19 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
function block_test($n = 20000)
{
for ($i = 0; $i < $n; $i++) {
$randStr = RandStr::gen(15);
$host = "www.i_$randStr.com";
swoole_async_dns_lookup($host, function($host, $ip) use($i) {
echo "FIN i -> $ip\n";
});
}
}
block_test();

View File

@ -0,0 +1,77 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//swoole_function swoole_async_read($filename, $callback, $chunk_size = null, $offset = null) {}
//swoole_function swoole_async_write($filename, $content, $offset = null, $callback = null) {}
//swoole_function swoole_async_readfile($filename, $callback) {}
//swoole_function swoole_async_writefile($filename, $content, $callback = null) {}
// WARNING zif_swoole_async_readfile: file_size[size=1073741824|max_size=4194304] is too big. Please use swoole_async_read.
function rw_small_file() {
$file = __DIR__ . "/small_zero";
@unlink($file);
@unlink("$file.copy");
$len = 1024 * 1024 * 4; // 4M
$put_len = file_put_contents($file, str_repeat("\0", $len), FILE_APPEND);
assert($put_len === $len);
swoole_async_readfile($file, function($filename, $content) use($file) {
swoole_async_writefile("$file.copy", $content, function($write_file) use($file) {
// echo "copy small file finish\n";
// echo `ls -alh | grep zero`;
assert(filesize($write_file) === filesize($file));
unlink($write_file);
unlink($file);
echo "SUCCESS";
});
});
}
function rw_big_file() {
$file = __DIR__ . "/big_zero";
@unlink($file);
@unlink("$file.copy");
// 生成1G文件
for($i = 0; $i < 1024; $i++) {
$len = 1024 * 1024;
$put_len = file_put_contents($file, str_repeat("\0", $len), FILE_APPEND);
assert($put_len === $len);
}
// chunk = 1M copy
$i = 0;
swoole_async_read($file, function($filename, $content) use($file, &$i) {
// echo "read " . strlen($content) . " size\n";
$continue = true;
if (empty($content)) {
$continue = false;
}
$offset = $i * 1024 * 1024;
// echo "write offset $offset\n";
swoole_async_write("$file.copy", $content, $offset, function($write_file, $len) use($file, &$i, $continue) {
// echo "write $len size\n";
$i++;
if ($continue === false) {
// echo "copy finished\n";
// echo `ls -alh | grep zero`;
sleep(1);
assert(filesize($write_file) === filesize($file));
unlink($file);
unlink($write_file);
echo "SUCCESS";
}
});
return $continue;
}, 1024 * 1024);
}
rw_small_file();
rw_big_file();

View File

@ -0,0 +1,66 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//swoole_function swoole_async_read($filename, $callback, $chunk_size = null, $offset = null) {}
function read_dev_zero()
{
$context = file_get_contents("/dev/zero", null, null, null, 8192);
assert(strlen($context) === 8192);
// TODO WARNING zif_swoole_async_read: offset must be less than file_size[=0].
swoole_async_read("/dev/zero", function ($filename, $content) {
echo "file: $filename\ncontent-length: " . strlen($content) . "\nContent: $content\n";
if (empty($content)) {
echo "file is end.\n";
return false;
} else {
return true;
}
}, 8192);
}
function read_dev_null()
{
$context = file_get_contents("/dev/null", null, null, null, 8192);
assert(strlen($context) === 0);
// TODO WARNING zif_swoole_async_read: offset must be less than file_size[=0].
swoole_async_read("/dev/null", function ($filename, $content) {
echo "file: $filename\ncontent-length: " . strlen($content) . "\nContent: $content\n";
if (empty($content)) {
echo "file is end.\n";
return false;
} else {
return true;
}
}, 8192);
}
function read_normal_file()
{
$context = file_get_contents(__FILE__, null, null, null, 8192);
$len = strlen($context);
swoole_async_read(__FILE__, function ($filename, $content) use($len) {
echo "read callback\n";
// echo $len, "\n";
// echo strlen($content), "\n";
// assert($len === strlen($content));
if (empty($content)) {
echo "file is end.\n";
return false;
} else {
return true;
}
}, 8192);
}
read_dev_zero();
read_dev_null();
read_normal_file();
// todo read 大文件

View File

@ -0,0 +1,62 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//swoole_function swoole_async_readfile($filename, $callback) {}
function read_dev_zero()
{
$context = file_get_contents("/dev/zero", null, null, null, 8192);
assert(strlen($context) === 8192);
// TODO WARNING zif_swoole_async_readfile: file is empty.
swoole_async_readfile("/dev/zero", function ($filename, $content) {
echo "file: $filename\ncontent-length: " . strlen($content) . "\nContent: $content\n";
if (empty($content)) {
echo "file is end.\n";
return false;
} else {
return true;
}
});
}
function read_dev_null()
{
$context = file_get_contents("/dev/null", null, null, null, 8192);
assert(strlen($context) === 0);
// TODO WARNING zif_swoole_async_readfile: file is empty.
swoole_async_readfile("/dev/null", function ($filename, $content) {
echo "file: $filename\ncontent-length: " . strlen($content) . "\nContent: $content\n";
if (empty($content)) {
echo "file is end.\n";
return false;
} else {
return true;
}
});
}
function read_normal_file()
{
$context = file_get_contents(__FILE__, null, null, null, 8192);
$len = strlen($context);
swoole_async_readfile(__FILE__, function ($filename, $content) use($len) {
echo "read callback\n";
if (empty($content)) {
echo "file is end.\n";
return false;
} else {
return true;
}
});
}
read_dev_zero();
read_dev_null();
read_normal_file();
// todo read 大文件

View File

@ -0,0 +1,67 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//swoole_function swoole_async_write($filename, $content, $offset = null, $callback = null) {}
//callback: return true: write contine. return false: close the file.
function write_dev_zero()
{
$data = str_repeat("\0", 8192);
$len = file_put_contents("/dev/zero", $data);
assert($len === 8192);
for ($i = 0; $i < 100; $i++) {
swoole_async_write("/dev/zero", $data, -1, function ($file, $len) {
echo "write /dev/zero $len size\n";
return true;
});
}
}
function write_dev_null()
{
$data = str_repeat("\0", 8192);
$len = file_put_contents("/dev/null", $data);
assert($len === 8192);
for ($i = 0; $i < 100; $i++) {
swoole_async_write("/dev/null", $data, -1, function ($file, $len) {
echo "write /dev/null $len size\n";
return true;
});
}
}
function write_normal_file()
{
$file = __DIR__ . "/zero";
$data = str_repeat("\0", 8192);
$len = file_put_contents($file, $data);
assert($len === 8192);
unlink($file);
/** @noinspection PhpUnusedLocalVariableInspection
* @param int $dep
*/
$recursiveWrite = function($dep = 0) use($data, &$recursiveWrite, $file) {
swoole_async_write($file, $data, -1, function ($file, $len) use(&$recursiveWrite, $dep) {
if ($dep > 100) {
unlink($file);
return false;
}
echo "write $file $len size\n";
$recursiveWrite(++$dep);
return true;
});
};
$recursiveWrite();
}
write_dev_zero();
write_dev_null();
write_normal_file();

View File

@ -0,0 +1,63 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//swoole_function swoole_async_writefile($filename, $content, $callback = null) {}
function write_dev_zero()
{
$data = str_repeat("\0", 8192);
$len = file_put_contents("/dev/zero", $data);
assert($len === 8192);
for ($i = 0; $i < 100; $i++) {
swoole_async_writefile("/dev/zero", $data, function ($file, $len) {
echo "write /dev/zero $len size\n";
});
}
}
function write_dev_null()
{
$data = str_repeat("\0", 8192);
$len = file_put_contents("/dev/null", $data);
assert($len === 8192);
for ($i = 0; $i < 100; $i++) {
swoole_async_writefile("/dev/null", $data, function ($file, $len) {
echo "write /dev/null $len size\n";
});
}
}
function write_normal_file()
{
$file = __DIR__ . "/zero";
$data = str_repeat("\0", 8192);
$len = file_put_contents($file, $data);
assert($len === 8192);
unlink($file);
/** @noinspection PhpUnusedLocalVariableInspection
* @param int $dep
*/
$recursiveWrite = function($dep = 0) use($data, &$recursiveWrite, $file) {
swoole_async_writefile($file, $data, function ($file, $len) use(&$recursiveWrite, $dep) {
if ($dep > 100) {
unlink($file);
return;
}
echo "write $file $len size\n";
$recursiveWrite(++$dep);
});
};
$recursiveWrite();
}
write_dev_zero();
write_dev_null();
write_normal_file();

View File

@ -0,0 +1,19 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
function block_test($n = 20000)
{
for ($i = 0; $i < $n; $i++) {
$randStr = RandStr::gen(15);
$host = "www.i_$randStr.com";
swoole_async_dns_lookup($host, function($host, $ip) use($i) {
echo "FIN i -> $ip\n";
});
}
}
block_test();

View File

@ -0,0 +1,42 @@
<?php
// Cannot destroy active lambda swoole_function
// 先用nc起一个 swoole_server
// nc -4lk 9090
send("hello", function($cli, $data) {
var_dump($data);
send("hello", function($cli, $data) {
var_dump($data);
send("hello", function($cli, $data) {
var_dump($data);
});
});
});
function send($str, $onRecv)
{
static $client;
if ($client === null) {
$client = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$client->on("error", function($cli) { echo "error"; });
$client->on("close", function($cli) { echo "close"; });
$client->on("connect", function($cli) use($str, $onRecv) {
send($str, $onRecv);
});
}
// !!! Fatal error: Cannot destroy active lambda swoole_function
$client->on("receive", $onRecv);
if ($client->isConnected()) {
$client->send("PING");
} else {
$client->connect("127.0.0.1", 9090);
}
}

View File

@ -0,0 +1,11 @@
<?php
$cli = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$cli->on("connect", function(swoole_client $cli) {
assert(false);
});
$cli->on("receive", function(swoole_client $cli, $data) {
assert(false);
});
$cli->on("error", function(swoole_client $cli) { echo "connect timeout\n"; });
$cli->on("close", function(swoole_client $cli) { echo "close\n"; });
$cli->connect("11.11.11.11", 9000, 0.5);

View File

@ -0,0 +1,34 @@
<?php
$start = microtime(true);
$cli = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$cli->on("connect", function(swoole_client $cli) {
assert(false);
});
$cli->on("receive", function(swoole_client $cli, $data) {
assert(false);
});
$cli->on("error", function(swoole_client $cli) {
echo "error\n";
});
$cli->on("close", function(swoole_client $cli) {
echo "close\n";
});
function refcount($var)
{
ob_start();
debug_zval_dump($var);
preg_match('/refcount\((?<refcount>\d)\)/', ob_get_clean(), $matches);
return intval($matches["refcount"]) - 3;
}
@$cli->connect("11.11.11.11", 9000, 0.1);
@$cli->connect("11.11.11.11", 9000, 0.1);
@$cli->connect("11.11.11.11", 9000, 0.1);
@$cli->connect("11.11.11.11", 9000, 0.1);
@$cli->connect("11.11.11.11", 9000, 0.1);
Swoole\Event::wait();
// xdebug_debug_zval("cli");
// echo refcount($cli); // php7无效

View File

@ -0,0 +1,48 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
// suicide(5000);
$cli = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
/** @noinspection PhpVoidFunctionResultUsedInspection */
assert($cli->set([
'open_length_check' => 1,
'package_length_type' => 'N',
'package_length_offset' => 0,
'package_body_offset' => 0,
]));
$cli->on("connect", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
assert($cli->isConnected() === true);
});
$cli->on("receive", function(swoole_client $cli, $data){
$cli->close();
assert($cli->isConnected() === false);
});
$cli->on("error", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
echo "ERROR";
});
$cli->on("close", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
echo "CLOSE";
});
$cli->connect(TCP_SERVER_HOST, TCP_SERVER_PORT);
$cli->timeo_id = swoole_timer_after(1000, function() use($cli) {
debug_log("connect timeout");
$cli->close();
assert($cli->isConnected() === false);
});

View File

@ -0,0 +1,63 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
suicide(5000);
$cli = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
/** @noinspection PhpVoidFunctionResultUsedInspection */
assert($cli->set([
// TODO test
// 'open_eof_check' => true,
// 'package_eof' => "\r\n\r\n",
// TODO
// "socket_buffer_size" => 1,
]));
$cli->on("connect", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
// TODO getSocket BUG
// assert(is_resource($cli->getSocket()));
/*
$cli->getSocket();
// Warning: swoole_client_async::getSocket(): unable to obtain socket family Error: Bad file descriptor[9].
$cli->getSocket();
*/
assert($cli->isConnected() === true);
$cli->send(RandStr::gen(1024, RandStr::ALL));
// $cli->sendfile(__DIR__.'/test.txt');
});
$cli->on("receive", function(swoole_client $cli, $data){
$recv_len = strlen($data);
debug_log("receive: len $recv_len");
$cli->send(RandStr::gen(1024, RandStr::ALL));
$cli->close();
assert($cli->isConnected() === false);
});
$cli->on("error", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
debug_log("error");
});
$cli->on("close", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
debug_log("close");
});
$cli->connect(TCP_SERVER_HOST, TCP_SERVER_PORT);
$cli->timeo_id = swoole_timer_after(1000, function() use($cli) {
debug_log("connect timeout");
$cli->close();
assert($cli->isConnected() === false);
});

View File

@ -0,0 +1,48 @@
<?php
// swoole socket 复用BUG
function onClose(swoole_client $cli) {
$fd = \EventUtil::getSocketFd($cli->getSocket());
echo "close fd <$fd>\n";
}
function onError(swoole_client $cli) {
$fd = \EventUtil::getSocketFd($cli->getSocket());
echo "error fd <$fd>\n";
}
$host = "127.0.0.1";
$port = 8050;
$cli = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$cli->on("receive", function(swoole_client $cli, $data){ });
$cli->on("error", "onError");
$cli->on("close", "onClose");
$cli->on("connect", function(swoole_client $cli) use($host, $port) {
$fd = \EventUtil::getSocketFd($cli->getSocket());
echo "connected fd <$fd>\n";
$cli->close(); // close(fd)
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
$newCli = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$newCli->on("receive", function(swoole_client $cli, $data){ });
$newCli->on("error", "onError");
$newCli->on("close", "onClose");
$newCli->on("connect", function(swoole_client $newCli) use($cli) {
$fd = \EventUtil::getSocketFd($cli->getSocket());
echo "connected fd <$fd>, reuse!!!\n";
echo "free socket\n";
$cli->__destruct();
echo "send\n";
$r = $newCli->send("HELLO");
});
$newCli->connect($host, $port);
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
});
$cli->connect($host, $port);

View File

@ -0,0 +1,16 @@
<?php
function main() {
$cli = new \swoole_http_client("11.11.11.11", 9000);
$cli->on('close', function($cli) {
assert(false);
});
$cli->on('error', function($cli) {
echo "error";
});
$cli->get('/', function(swoole_http_client $cli) {});
}
main();

View File

@ -0,0 +1,12 @@
<?php
$cli = new swoole_http_client("127.0.0.1", 65535);
$cli->on('close', function($cli) {
echo "close\n";
});
$cli->on('error', function($cli) {
echo "error\n";
});
$cli->get('/', function(swoole_http_client $cli) {});

View File

@ -0,0 +1,19 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
$cli = new \swoole_http_client("127.0.0.1", 65535);
$cli->on('close', function($cli) {
echo 'close\n';
});
$cli->on('error', function($cli) {
echo "error\n";
});
swoole_timer_after(500, function() {
swoole_event_exit();
echo "time out\n";
});
$cli->get('/', function(swoole_http_client $cli) {});

View File

@ -0,0 +1,10 @@
<?php
$httpClient = new swoole_http_client("11.11.11.11", 9000);
$httpClient->set(['timeout' => 1]);
$httpClient->get("/", function ($client)
{
assert($client->errCode == 110);
assert($client->statusCode == -1);
assert(!$client->body);
});

View File

@ -0,0 +1,38 @@
<?php
// swoole_server
$s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_setopt($s, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($s, "127.0.0.1", 9090);
socket_listen($s);
$func = "hello";
while($conn = socket_accept($s)) {
socket_write($conn, "HTTP/1.1 200 OK\r\n\r\n");
socket_write($conn, "HTTP/1.1 200 OK\r\nX-Func: {$func}\r\n\r\n");
socket_close($conn);
}
// client
function hello() {
echo "\n\nhello world!\n\n";
swoole_event_exit();
exit();
}
function req() {
$cli = new swoole_http_client("127.0.0.1", 9090);
$cli->on("close", function() {
req();
});
$cli->get("/", function(swoole_http_client $cli) {
echo "receive:", $cli->body, "\n";
});
}
req();

View File

@ -0,0 +1,27 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
// 旧版本因为没有做判断, 构造失败之后, 之后调用close会core
function error_close_test($desc, $ip, $port)
{
$cli = new swoole_http_client($ip, $port);
$cli->on("error", function() use($desc) { echo "$desc error\n"; });
$cli->on("close", function() use($desc) { echo "$desc close\n"; });
$cli->get("/", function($cli){ });
swoole_timer_after(1000, function() use($cli) { $cli->close(); });
}
// 触发close 回调
error_close_test("baidu", "115.239.211.112", 80);
// 触发error回调
error_close_test("localhost", "127.0.0.1", 9090);
// TODO 此处行为不正确
// 应该校验参数是否合法ip, 抛出异常(构造函数无法返回错误)
error_close_test("\\0", "\0", 9090);
// TODO 同上
error_close_test("", "null string", 9090);

View File

@ -0,0 +1,27 @@
<?php
function create()
{
$cli = new swoole_http_client("127.0.0.1", 80);
$cli->setHeaders([
"Host" => "xxx.xxx.xxx",
]);
$cli->on("error", function() { echo "error"; });
$cli->on("close", function() { echo "close\n\n"; post(create()); });
return $cli;
}
post(create());
function post($cli) {
$cli->post("/xxx/xxx/xxx", [
"ua" => "younipf",
"debug" => "json",
], function($cli) {
echo $cli->statusCode, "\n";
post($cli);
});
}
$payload = <<<HTML
HTTP/1.1 400 Bad Request\r\nDate: Fri, 10 Mar 2017 10:47:07 GMT\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 242\r\nConnection: close\r\n\r\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<html>\r\n<head><title>400 Bad Request</title></head>\r\n<body bgcolor=\"white\">\r\n<h1>400 Bad Request</h1>\r\n<p>Your browser sent a request that this swoole_server could not understand.</body>\r\n</html>\r\n
HTML;

View File

@ -0,0 +1,352 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
function makeHttpClient($host = HTTP_SERVER_HOST, $port = HTTP_SERVER_PORT, $ssl = false, $output = false, callable $done = null)
{
$httpClient = new \swoole_http_client($host, $port, $ssl);
$httpClient->set([
"socket_buffer_size" => 1024 * 1024 * 2,
'timeout' => 1.0,
]);
if ($ssl) {
$httpClient->set([
'ssl_cert_file' => __DIR__ . '../swoole_http_server/localhost-ssl/swoole_server.crt',
'ssl_key_file' => __DIR__ . '../swoole_http_server/localhost-ssl/swoole_server.key',
]);
}
$httpClient->on("connect", function(\swoole_http_client $httpClient) {
assert($httpClient->isConnected() === true);
// debug_log("connect");
});
$httpClient->on("error", function(\swoole_http_client $httpClient) use($output, $done) {
if ($output) {
echo "error";
}
if ($done) {
$done();
}
// debug_log("error");
});
$httpClient->on("close", function(\swoole_http_client $httpClient) use($output, $done) {
if ($output) {
echo "close";
}
if ($done) {
$done();
}
// debug_log("close");
});
return $httpClient;
}
function testUri($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
$ok = $httpClient->get("/uri", function(\swoole_http_client $httpClient) use($fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
assert($httpClient->body === "/uri");
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testHttpGet($host, $port, array $query, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
$queryStr = http_build_query($query);
$ok = $httpClient->get("/get?$queryStr", function (\swoole_http_client $httpClient) use ($query, $fin, $queryStr)
{
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
if ($queryStr === "")
{
assert($httpClient->body === "null");
}
else
{
$ret = json_decode($httpClient->body, true);
assert(arrayEqual($ret, $query, false));
}
if ($fin)
{
$fin($httpClient);
}
});
assert($ok);
}
function testPost($host, $port, array $query, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
$ok = $httpClient->post("/post", $query, function(\swoole_http_client $httpClient) use($query, $fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
// $httpClient->headers;
$ret = json_decode($httpClient->body, true);
assert(arrayEqual($ret, $query, false));
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testMethod($host, $port, $method, $data = null, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
$ok = $httpClient->setMethod($method);
assert($ok);
if ($data) {
$httpClient->setData($data);
}
$ok = $httpClient->execute("/method", function(\swoole_http_client $httpClient) use($method, $fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
assert($httpClient->body === $method);
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testCookie($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
$ok = $httpClient->setCookies(["hello" => "world"]);
assert($ok);
$ok = $httpClient->get("/cookie", function(\swoole_http_client $httpClient) use($fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
assert($httpClient->body === "{\"hello\":\"world\"}");
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
// setCookies 已经加入类型限制
function testCookieCore($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
$ok = $httpClient->setCookies("hello=world; path=/;");
assert($ok);
$ok = $httpClient->get("/cookie", function(\swoole_http_client $httpClient) use($fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
assert($httpClient->body === "null");
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testHeader($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
$httpClient->setting += ["keep_alive" => true];
// TODO 只要调用setHeaders 则会变为 connection close
$ok = $httpClient->setHeaders(["hello" => "world"]);
assert($ok);
$ok = $httpClient->get("/header", function(\swoole_http_client $httpClient) use($fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
$headers = json_decode($httpClient->body, true);
assert(isset($headers["hello"]) && $headers["hello"] === "world");
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
// 已经修复
function testHeaderCore($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
// $httpClient->setting += ["keep_alive" => true];
// COREDUMP
// 旧版传递字符串会发生coredump
// $httpClient->setHeaders("Hello: World\r\nHello: World\r\n");
$r = $httpClient->setHeaders(["\0" => "\0"]);
$ok = $httpClient->get("/header", function(\swoole_http_client $httpClient) use($fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
$headers = json_decode($httpClient->body, true);
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testSleep($host, $port)
{
$httpClient = makeHttpClient($host, $port);
$ok = $httpClient->get("/sleep", function(\swoole_http_client $httpClient) {
assert(false);
});
assert($ok);
}
// http message 分多次接受有问题 (10k message)
function testBigBodyMethodNotSupport($host, $port, callable $fin = null)
{
if ($fin) {
$httpClient = makeHttpClient($host, $port, false, true, $fin);
} else {
$httpClient = makeHttpClient($host, $port, false, true);
}
$body = str_repeat("\0", 10240);
$ok = $httpClient->post("/", $body, function(\swoole_http_client $httpClient) use($fin) {
echo "SUCCESS\n";
});
assert($ok);
}
// http message 分多次接受有问题 (间隔1s发送)
function testBigBodyMethodNotSupport2($host, $port, callable $fin = null)
{
$cli = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$cli->on("connect", function(swoole_client $cli) {
$cli->send("POST / HTTP/1.0\r\nHost: 127.0.0.1\r\nConnection: close\r\nContent-Length: 1\r\n\r\n");
swoole_timer_after(1, function() use($cli) {
$cli->send("\0");
});
});
$cli->on("receive", function(swoole_client $cli, $data){
echo "SUCCESS";
});
$cli->on("error", function(swoole_client $cli) use($fin) {
echo "error";
if ($fin) {
$fin();
}
});
$cli->on("close", function(swoole_client $cli) use($fin) {
echo "close";
if ($fin) {
$fin();
}
});
$cli->connect($host, $port);
}
function testSendfile($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
$httpClient->setMethod("GET");
$ok = $httpClient->execute("/file", function(\swoole_http_client $httpClient) use($fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testRawCookie($host, $port, $cookie, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
$httpClient->setMethod("POST");
$httpClient->setData($cookie);
$ok = $httpClient->execute("/rawcookie", function(\swoole_http_client $httpClient) use($fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testRawcontent($host, $port, $data, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
if ($data !== false) {
$httpClient->setData($data);
}
$httpClient->setMethod("POST");
$ok = $httpClient->execute("/rawcontent", function(\swoole_http_client $httpClient) use($fin, $data) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testExecute($host, $port, $method, $data, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port);
if ($data !== false) {
$httpClient->setData($data);
}
if ($method) {
$httpClient->setMethod("POST");
}
$ok = $httpClient->execute("/content_length", function(\swoole_http_client $httpClient) use($fin, $data) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function request($host, $port, $method, $url, $body, array $header, array $cookie, callable $finish)
{
$httpClient = makeHttpClient($host, $port);
$httpClient->setMethod($method);
if ($cookie) {
$httpClient->setCookies($cookie);
}
if ($header) {
$httpClient->setCookies($header);
}
if ($body) {
$httpClient->setData($body);
}
$httpClient->setting += ["keep_alive" => false];
$httpClient->execute($url, function(\swoole_http_client $httpClient) use($finish) {
$finish($httpClient);
$httpClient->close();
});
}

View File

@ -0,0 +1,75 @@
<?php
`pkill php-fpm`;
require __DIR__ . "/../../../include/bootstrap.php";
require_once __DIR__ . "/simple_http_client.php";
$host = HTTP_SERVER_HOST;
$port = HTTP_SERVER_PORT;
$data = null;
testExecute($host, $port, null, $data, function($httpClient) use($data) {
assert(0 === intval($httpClient->body));
echo "SUCCESS";
});
$data = null;
testExecute($host, $port, "POST", $data, function($httpClient) use($data) {
assert(0 === intval($httpClient->body));
echo "SUCCESS";
});
$data = RandStr::gen(rand(0, 1024));
testExecute($host, $port, "POST", $data, function($httpClient) use($data) {
assert(strlen($data) === intval($httpClient->body));
echo "SUCCESS";
});
exit;
testHttpsHeaderCore($host, $port);
testUri($host, $port);
testUri($host, $port);
testGet($host, $port, []);
testGet($host, $port, $_SERVER);
testPost($host, $port, $_SERVER);
testMethod($host, $port, "GET");
testMethod($host, $port, "DELETE");
testMethod($host, $port, "POST", "payload");
testMethod($host, $port, "PUT", "payload");
testMethod($host, $port, "PATCH", "payload");
// TODO bug, 没有校验
// testMethod($host, $port, "GET", "http_body");
// testMethod($host, $port, "DELETE", "http_body");
//testMethod($host, $port, "POST", null);
//testMethod($host, $port, "PUT", null);
//testMethod($host, $port, "PATCH", null);
testCookie($host, $port);
// TODO coredump
// testCookieCore($host, $port);
testHttpsHeaderCore($host, $port);
testHeader($host, $port);
testSleep($host, $port);
//request($host, $port, "GET", "/", null,
// ["cookie_key" => "cookie_value"],
// ["header_key" => "header_value"],
// swoole_function(swoole_http_client $cli) {
// assert($cli->body === "Hello World!");
// });

View File

@ -0,0 +1,280 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
/*
class swoole_http_client
{
public swoole_function __construct() {}
public swoole_function __destruct() {}
public swoole_function set() {}
public swoole_function setMethod() {}
public swoole_function setHeaders() {}
public swoole_function setCookies() {}
public swoole_function setData() {}
public swoole_function execute() {}
public swoole_function push() {}
public swoole_function get() {}
public swoole_function post() {}
public swoole_function isConnected() {}
public swoole_function close() {}
public swoole_function on() {}
}
*/
function addTimer(\swoole_http_client $httpClient)
{
if (property_exists($httpClient, "timeo_id")) {
return false;
}
return $httpClient->timeo_id = swoole_timer_after(1000, function() use($httpClient) {
debug_log("http request timeout");
// TODO 超时强制关闭连接 server端: ERROR swFactoryProcess_finish (ERROR 1005): session#%d does not exist.
$httpClient->close();
assert($httpClient->isConnected() === false);
});
}
function cancelTimer($httpClient)
{
if (property_exists($httpClient, "timeo_id")) {
$ret = swoole_timer_clear($httpClient->timeo_id);
unset($httpClient->timeo_id);
return $ret;
}
return false;
}
function makeHttpClient($host = HTTP_SERVER_HOST, $port = HTTP_SERVER_PORT, $ssl = true)
{
$httpClient = new \swoole_http_client($host, $port, $ssl);
$httpClient->set([
'timeout' => 1,
"socket_buffer_size" => 1024 * 1024 * 2,
]);
if ($ssl) {
$httpClient->set([
'ssl_cert_file' => __DIR__ . '/../swoole_http_server/localhost-ssl/server.crt',
'ssl_key_file' => __DIR__ . '/../swoole_http_server/localhost-ssl/server.key',
]);
}
$httpClient->on("connect", function(\swoole_http_client $httpClient) {
assert($httpClient->isConnected() === true);
// debug_log("connect");
});
$httpClient->on("error", function(\swoole_http_client $httpClient) {
// debug_log("error");
});
$httpClient->on("close", function(\swoole_http_client $httpClient) {
// debug_log("close");
});
return $httpClient;
}
function testUri($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port, true);
addTimer($httpClient);
$ok = $httpClient->get("/uri", function(\swoole_http_client $httpClient) use($fin) {
cancelTimer($httpClient);
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
assert($httpClient->body === "/uri");
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testHttpsGet($host, $port, array $query, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port, true);
$queryStr = http_build_query($query);
$ok = $httpClient->get("/get?$queryStr", function(\swoole_http_client $httpClient) use($query, $fin, $queryStr) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
// $httpClient->headers;
if ($queryStr === "") {
assert($httpClient->body === "null");
} else {
$ret = json_decode($httpClient->body, true);
assert(arrayEqual($ret, $query, false));
}
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testPost($host, $port, array $query, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port, true);
$ok = $httpClient->post("/post", $query, function(\swoole_http_client $httpClient) use($query, $fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
// $httpClient->headers;
$ret = json_decode($httpClient->body, true);
assert(arrayEqual($ret, $query, false));
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testMethod($host, $port, $method, $data = null, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port, true);
addTimer($httpClient);
$ok = $httpClient->setMethod($method);
assert($ok);
if ($data) {
$httpClient->setData($data);
}
$ok = $httpClient->execute("/method", function(\swoole_http_client $httpClient) use($method, $fin) {
cancelTimer($httpClient);
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
assert($httpClient->body === $method);
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testCookie($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port, true);
addTimer($httpClient);
$ok = $httpClient->setCookies(["hello" => "world"]);
assert($ok);
$ok = $httpClient->get("/cookie", function(\swoole_http_client $httpClient) use($fin) {
cancelTimer($httpClient);
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
assert($httpClient->body === "{\"hello\":\"world\"}");
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testCookieCore($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port, true);
addTimer($httpClient);
$ok = $httpClient->setCookies("hello=world; path=/;");
assert($ok);
$ok = $httpClient->get("/cookie", function(\swoole_http_client $httpClient) use($fin) {
cancelTimer($httpClient);
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
var_dump($httpClient->body);
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testHeader($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port, true);
addTimer($httpClient);
$httpClient->setting += ["keep_alive" => true];
// TODO 只要调用setHeaders 则会变为 connection close
$ok = $httpClient->setHeaders(["hello" => "world"]);
assert($ok);
$ok = $httpClient->get("/header", function(\swoole_http_client $httpClient) use($fin) {
cancelTimer($httpClient);
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
$headers = json_decode($httpClient->body, true);
assert(isset($headers["hello"]) && $headers["hello"] === "world");
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
// 已经修复
function testHttpsHeaderCore($host, $port, callable $fin = null)
{
$httpClient = makeHttpClient($host, $port, true);
// $httpClient->setting += ["keep_alive" => true];
// COREDUMP
// 旧版传递字符串会发生coredump
// $httpClient->setHeaders("Hello: World\r\nHello: World\r\n");
$r = $httpClient->setHeaders(["\0" => "\0"]);
$ok = $httpClient->get("/header", function(\swoole_http_client $httpClient) use($fin) {
assert($httpClient->statusCode === 200);
assert($httpClient->errCode === 0);
$headers = json_decode($httpClient->body, true);
if ($fin) {
$fin($httpClient);
}
});
assert($ok);
}
function testSleep($host, $port)
{
$httpClient = makeHttpClient($host, $port, true);
addTimer($httpClient);
$ok = $httpClient->get("/sleep", function(\swoole_http_client $httpClient) {
assert(false);
});
assert($ok);
}
function request($host, $port, $method, $url, $body, array $header, array $cookie, callable $finish)
{
$httpClient = makeHttpClient($host, $port, true);
addTimer($httpClient);
$httpClient->setMethod($method);
if ($cookie) {
$httpClient->setCookies($cookie);
}
if ($header) {
$httpClient->setCookies($header);
}
if ($body) {
$httpClient->setData($body);
}
$httpClient->setting += ["keep_alive" => false];
$httpClient->execute($url, function(\swoole_http_client $httpClient) use($finish) {
cancelTimer($httpClient);
$finish($httpClient);
$httpClient->close();
});
}

View File

@ -0,0 +1,44 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
require_once __DIR__ . "/simple_https_client.php";
//request($host, $port, "GET", "/", null,
// ["cookie_key" => "cookie_value"],
// ["header_key" => "header_value"],
// swoole_function(swoole_http_client $cli) {
// assert($cli->body === "Hello World!");
// });
testUri($host, $port);
testGet($host, $port, []);
testGet($host, $port, $_SERVER);
testPost($host, $port, $_SERVER);
testMethod($host, $port, "GET");
testMethod($host, $port, "DELETE");
testMethod($host, $port, "POST", "payload");
testMethod($host, $port, "PUT", "payload");
testMethod($host, $port, "PATCH", "payload");
// TODO bug, 没有校验
// testMethod($host, $port, "GET", "http_body");
// testMethod($host, $port, "DELETE", "http_body");
//testMethod($host, $port, "POST", null);
//testMethod($host, $port, "PUT", null);
//testMethod($host, $port, "PATCH", null);
testCookie($host, $port);
// TODO coredump
// testCookieCore();
testHttpsHeaderCore($host, $port);
testHeader($host, $port);
testSleep($host, $port);

View File

@ -0,0 +1,33 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
// 旧版本一个bug, 连接收到RST会coredump
// 1. 对端发送RST
// 2. 对端不回任何segment
function test_connect_refused()
{
static $clients = [];
$hosts = ["115.239.211.112", "127.0.0.1", "11.11.11.11"];
for ($i = 0; $i < 2000; $i++) {
$host = $hosts[$i % 3];
$port = 8000 + $i;
echo "get $host:$port\n";
$cli = new swoole_http_client($host, $port);
$cli->setHeaders(["Connection" => "close"]);
$cli->get("/", function(swoole_http_client $cli) {
echo "receive:", $cli->body, "\n";
});
swoole_timer_after(3000, function() use($cli, &$clients) {
$cli->close();
unset($clients[spl_object_hash($cli)]);
});
$clients[spl_object_hash($cli)] = $cli; // 防止swoole 引用计数处理错误
}
}
test_connect_refused();

View File

@ -0,0 +1,10 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
$cli = new swoole_http_client("115.239.211.112", 80);
$cli->setHeaders(["Connection" => "close"]);
$cli->get("/", function(swoole_http_client $cli) {
echo "receive:", $cli->body, "\n";
});

View File

@ -0,0 +1,41 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
/*
require('net').createServer(swoole_function(socket) {
socket.on('data', swoole_function(data) {
socket.write('HTTP/1.1 200 OK\r\n');
socket.write('Transfer-Encoding: chunked\r\n');
socket.write('\r\n');
var php_func = "hello"
// var php_func = "ReflectionClass::export"
socket.write('4\r\n');
socket.write('func\r\n');
socket.write('0\r\n');
socket.write('\r\n');
socket.write('HTTP/1.1 200 OK\r\n');
socket.write('Transfer-Encoding: ' + php_func + '\r\n');
socket.write('\r\n');
});
}).listen(9090, '127.0.0.1');
*/
// 旧版本会因为因为 use after free
// 回调的zval 指向 parser header的zval
// 最后 call hello
function hello() {
echo "=======================================\n";
echo "call hello\n";
var_dump(func_get_args());
}
$cli = new swoole_http_client("127.0.0.1", 9090);
$cli->get("/", function(swoole_http_client $cli) {
echo "receive:", $cli->body, "\n";
});

View File

@ -0,0 +1,21 @@
require('net').createServer(function(socket) {
socket.on('data', function(data) {
socket.write('HTTP/1.1 200 OK\r\n');
socket.write('Transfer-Encoding: chunked\r\n');
socket.write('\r\n');
var php_func = "hello"
// var php_func = "ReflectionClass::export"
socket.write('4\r\n');
socket.write('func\r\n');
socket.write('0\r\n');
socket.write('\r\n');
// 故意构造两条响应
socket.write('HTTP/1.1 200 OK\r\n');
socket.write('Transfer-Encoding: ' + php_func + '\r\n');
socket.write('\r\n');
});
}).listen(9090, '127.0.0.1');

View File

@ -0,0 +1,11 @@
<?php
$http = new swoole_http_server("0.0.0.0", 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$http->set([
'ssl_cert_file' => __DIR__ . '/localhost-ssl/swoole_server.crt',
'ssl_key_file' => __DIR__ . '/localhost-ssl/swoole_server.key',
]);
$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();

View File

@ -0,0 +1,316 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
class HttpServer
{
/**
* @var \swoole_http_server
*/
public $httpServ;
public function __construct($host = HTTP_SERVER_HOST, $port = HTTP_SERVER_PORT, $ssl = false)
{
if ($ssl) {
$this->httpServ = new \swoole_http_server($host, $port, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
} else {
$this->httpServ = new \swoole_http_server($host, $port, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
}
$config = [
// 输出限制
"buffer_output_size" => 1024 * 1024 * 1024,
"max_connection" => 10240,
"pipe_buffer_size" => 1024 * 1024 * 1024,
// 'enable_port_reuse' => true,
'user' => 'www-data',
'group' => 'www-data',
'log_file' => '/tmp/swoole.log',
'dispatch_mode' => 3,
'open_tcp_nodelay' => 1,
'open_cpu_affinity' => 1,
'daemonize' => 0,
'reactor_num' => 1,
'worker_num' => 2,
'max_request' => 100000,
/*
'package_max_length' => 1024 * 1024 * 2
'open_length_check' => 1,
'package_length_type' => 'N',
'package_length_offset' => 0,
'package_body_offset' => 0,
'open_nova_protocol' => 1,
*/
];
if ($ssl)
{
$config['ssl_cert_file'] = __DIR__ . '/localhost-ssl/server.crt';
$config['ssl_key_file'] = __DIR__ . '/localhost-ssl/server.key';
}
$this->httpServ->set($config);
}
public function start()
{
$this->httpServ->on('start', [$this, 'onStart']);
$this->httpServ->on('shutdown', [$this, 'onShutdown']);
$this->httpServ->on('workerStart', [$this, 'onWorkerStart']);
$this->httpServ->on('workerStop', [$this, 'onWorkerStop']);
$this->httpServ->on('workerError', [$this, 'onWorkerError']);
$this->httpServ->on('connect', [$this, 'onConnect']);
$this->httpServ->on('receive', [$this, 'onReceive']);
$this->httpServ->on('request', [$this, 'onRequest']);
$this->httpServ->on('close', [$this, 'onClose']);
$sock = $this->httpServ->getSocket();
if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) {
echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
}
$this->httpServ->start();
}
public function onConnect()
{
debug_log("connecting ......");
}
public function onClose()
{
debug_log("closing .....");
}
public function onStart(\swoole_http_server $swooleServer)
{
debug_log("swoole_server starting .....");
}
public function onShutdown(\swoole_http_server $swooleServer)
{
debug_log("swoole_server shutdown .....");
}
public function onWorkerStart(\swoole_http_server $swooleServer, $workerId)
{
debug_log("worker #$workerId starting .....");
}
public function onWorkerStop(\swoole_http_server $swooleServer, $workerId)
{
debug_log("worker #$workerId stopping ....");
}
public function onWorkerError(\swoole_http_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
{
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
}
public function onReceive(\swoole_http_server $swooleServer, $fd, $fromId, $data)
{
$recv_len = strlen($data);
debug_log("receive: len $recv_len");
$swooleServer->send($fd, RandStr::gen($recv_len, RandStr::ALL));
}
public function onRequest(\swoole_http_request $request, \swoole_http_response $response)
{
$uri = $request->server["request_uri"];
if ($uri === "/favicon.ico") {
$response->status(404);
$response->end();
return;
}
testSetCookie:
{
$name = "name";
$value = "value";
// $expire = $request->swoole_server["request_time"] + 3600;
$expire = 0;
$path = "/";
$domain = "";
$secure = false;
$httpOnly = true;
// string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]]
$response->cookie($name, $value, $expire, $path, $domain, $secure, $httpOnly);
$expect = "name=value; path=/; httponly";
assert(in_array($expect, $response->cookie, true));
}
if ($uri === "/ping") {
$this->httpServ->send($request->fd, "HTTP/1.1 200 OK\r\nContent-Length: 4\r\n\r\npong\r\n");
return;
}
if ($uri === "/gzip") {
$level = 9;
$response->gzip($level);
$response->end(RandStr::gen(1024 * 1024 * 2, RandStr::ALL));
return;
}
if ($uri === "/info") {
ob_start();
print("request_uri: {$uri}\n");
print("request_method: {$request->server['request_method']}\n");
if (property_exists($request, "get")) {
print("get:" . var_export($request->get, true) . "\n");
}
if (property_exists($request, "post")) {
print("post:" . var_export($request->post, true) . "\n");
}
if (property_exists($request, "cookie")) {
print("cookie:" . var_export($request->cookie, true) . "\n");
}
if (property_exists($request, "header")) {
print("header:" . var_export($request->header, true) . "\n");
}
$response->end(nl2br(ob_get_clean()));
return;
}
if ($uri === "/uri") {
$response->end($request->server['request_uri']);
return;
}
if ($uri === "/method") {
$response->end($request->server['request_method']);
return;
}
if ($uri === "/get") {
if (!empty($request->get)) {
$response->end(json_encode($request->get));
} else {
$response->end("null");
}
return;
}
if ($uri === "/post") {
if (property_exists($request, "post")) {
$response->end(json_encode($request->post));
} else {
$response->end("{}");
}
return;
}
if ($uri === "/cookie") {
if (property_exists($request, "cookie")) {
$response->end(json_encode($request->cookie));
} else {
$response->end("{}");
}
return;
}
if ($uri === "/header") {
if (property_exists($request, "header")) {
$response->end(json_encode($request->header));
} else {
$response->end("{}");
}
return;
}
if ($uri === "/sleep") {
swoole_timer_after(1000, function() use($response) {
$response->end();
});
return;
}
if ($uri === "/404") {
$response->status(404);
$response->end();
return;
}
if ($uri === "/302") {
$response->header("Location", "http://www.swoole.com/");
$response->status(302);
$response->end();
return;
}
if ($uri === "/code") {
swoole_async_readfile(__FILE__, function($filename, $contents) use($response) {
$response->end(highlight_string($contents, true));
});
return;
}
if ($uri === "/json") {
$response->header("Content-Type", "application/json");
$response->end(json_encode($request->server, JSON_PRETTY_PRINT));
return;
}
if ($uri === "/chunked") {
$write = function($str) use($request) { return $this->httpServ->send($request->fd, $str); };
$write("HTTP/1.1 200 OK\r\n");
$write("Content-Encoding: chunked\r\n");
$write("Transfer-Encoding: chunked\r\n");
$write("Content-Type: text/html\r\n");
$write("Connection: keep-alive\r\n");
$write("\r\n");
// "0\r\n\r\n" finish
$writeChunk = function($str = "") use($write) {
$hexLen = dechex(strlen($str));
return $write("$hexLen\r\n$str\r\n");
};
$timer = swoole_timer_tick(200, function() use(&$timer, $writeChunk) {
static $i = 0;
$str = RandStr::gen($i++ % 40 + 1, RandStr::CHINESE) . "<br>";
if ($writeChunk($str) === false) {
swoole_timer_clear($timer);
}
});
return;
}
if ($uri === "/content_length") {
// $body = $request->rawcontent();
if (property_exists($request, "header")) {
if (isset($request->header['content-length'])) {
$response->end($request->header['content-length']);
} else {
$response->end(0);
}
return;
}
}
if ($uri === "/rawcontent") {
$response->end($request->rawcontent());
return;
}
if ($uri === "/file") {
$response->header("Content-Type", "text");
$response->header("Content-Disposition", "attachment; filename=\"test.php\"");
// TODO 这里会超时
$response->sendfile(__FILE__);
}
if ($uri === "/rawcookie") {
$response->cookie($name, $value, $expire, $path, $domain, $secure, $httpOnly);
$response->rawcookie("rawcontent", $request->rawcontent());
}
$response->end("Hello World!");
}
}

View File

@ -0,0 +1,10 @@
<?php
$host = isset($argv[1]) ? $argv[1] : HTTP_SERVER_HOST;
$port = isset($argv[2]) ? $argv[2] : HTTP_SERVER_PORT;
$httpServer = new swoole_http_server($host, $port);
$httpServer->on("request", function ($request, $response) {
});
$httpServer->start();

View File

@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICJTCCAY4CCQCyGHb21IPDXjANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJD
TjERMA8GA1UECBMIWmhlamlhbmcxETAPBgNVBAcTCEhhbmd6aG91MQ4wDAYDVQQK
EwVNeSBDQTESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE3MDIwOTA3NTExOVoXDTE3
MDMxMTA3NTExOVowVzELMAkGA1UEBhMCQ04xETAPBgNVBAgTCFpoZWppYW5nMREw
DwYDVQQHEwhIYW5nemhvdTEOMAwGA1UEChMFTXkgQ0ExEjAQBgNVBAMTCWxvY2Fs
aG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAkkn6a1CZrX/cDofktWZT
GDMIwIVfMsSOCSTBGTeQoCc7i/Zn6minMyJsD5+s3W6ctpja0JlwKt53ZVgNgrm9
H6NZyKNKqdWY8ElZwKE7nJ1LGlpS6nbY+M2VVedZLetU66+pi5/tAOsewRXkDemI
4xi6BRU4jIlvT84ovReklXUCAwEAATANBgkqhkiG9w0BAQUFAAOBgQAvGGt+nFvc
sfV/5oqJ43/wZvrA/NfLjtH2hJfBCMB+64gVgzVU/7FF35lTQwgDhAEidzUrUHVP
eI3hxJlVBBAGF5UjLx7rGOAPqm3Vm4C3Xkso90DZzSUo/se/R6bdpO+Iv1icLhFR
uGmMwQb/2DFpiy2XQojkoNwBvI1V9cHGGQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIBlzCCAQACAQAwVzELMAkGA1UEBhMCQ04xETAPBgNVBAgTCFpoZWppYW5nMREw
DwYDVQQHEwhIYW5nemhvdTEOMAwGA1UEChMFTXkgQ0ExEjAQBgNVBAMTCWxvY2Fs
aG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAkkn6a1CZrX/cDofktWZT
GDMIwIVfMsSOCSTBGTeQoCc7i/Zn6minMyJsD5+s3W6ctpja0JlwKt53ZVgNgrm9
H6NZyKNKqdWY8ElZwKE7nJ1LGlpS6nbY+M2VVedZLetU66+pi5/tAOsewRXkDemI
4xi6BRU4jIlvT84ovReklXUCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4GBAI+msopi
c6QIu0yYwPix0DyC8FEONih0kOQ//oe1bMLwbox/uxSoRmoJGiOdF7jqZceA0k8H
59SWMGzIUt5MRhDrye/7/LedXDVdCPacYLx7OzIlkBv9Dklk9o26jjT9u3Il7fQx
OfcCm2Lk+cwv3xXm6ZtEmklqKbnAnKd1oBfv
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCSSfprUJmtf9wOh+S1ZlMYMwjAhV8yxI4JJMEZN5CgJzuL9mfq
aKczImwPn6zdbpy2mNrQmXAq3ndlWA2Cub0fo1nIo0qp1ZjwSVnAoTucnUsaWlLq
dtj4zZVV51kt61Trr6mLn+0A6x7BFeQN6YjjGLoFFTiMiW9Pzii9F6SVdQIDAQAB
AoGAb2J8lbFtEbnE6Bt4fNZIdqiFBXGHprQaIcQmcvjn2cmFgXBAdy7v//M5rDu7
9239TNrd4O6zhTCWYEfHIb4izQlzj1WNwYm+9JCQ/ZLdD7B3e9IlYxcuw2QfmMJh
SLKITQSXLrCOlkRtRHCeKxC281p8jbpt7cwEPSZ9TNGP8QECQQDCvIXFUTKsb6Vc
UUcwCJBWucMlRA0njSqtcFU6G0LXSL8UspQMBM52T+fkQT1Hcx3rfUCPL9ywZvDG
7ECYDm6FAkEAwE+lhsuling0arIsI+IUT+N24iWYcC6Mq02MNa0A32KsOJs4oXxD
L50KFfsT3aW0V5KgaWipo/RwdQgkBHoWMQJACaauOok7qbAe0eR1UrwZ6zJpqX8l
57/nTZEzqB2Rwnmofq4bCD10vghXxcg18USTRwh+GpqUpWl0pWcwDFkqwQJATWaA
/4ytNtsEdcD6RQL0G+c37PMmtFf34+ZVPTFBPadQG4RVuaDyxZIWAhzItRfBStHH
4ETwqf1y2ZeKL4cXsQJAO0VLkDsUaepjfUMMYGw1cJeKm3ckdLb0+BKx9+Auxl2q
RgF3Nic7M09BbJxaRjjC47nyEA5wVg+G2DVgD4jI0A==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1 @@
BC864F1DFA88521C

View File

@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICKTCCAZICCQC8hk8d+ohSHDANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJD
TjERMA8GA1UECBMIWmhlamlhbmcxETAPBgNVBAcTCEhhbmd6aG91MQ4wDAYDVQQK
EwVNeSBDQTESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE3MDIwOTA3NTMxMloXDTE3
MDMxMTA3NTMxMlowWzELMAkGA1UEBhMCQ04xETAPBgNVBAgTCFpoZWppYW5nMREw
DwYDVQQHEwhIYW5nemhvdTESMBAGA1UEChMJTXkgQ2xpZW50MRIwEAYDVQQDEwls
b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJEUnBzXTTiyUmDb
yhkQoQ/yH1zTnuIk5Meg1Bp0fp1l4kwiizdPbZkk4YkTT/HXdTE6822Cqho+CwGE
VqWZyyd2AZmj87OGb4ZRCyyFzzjfEwdCTvyqZSUBoc1gvSGdEiaA4mXE87Y0XcMB
BasOrfmO76nuzyaXLT7xDjrB+Qw5AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAC09q
KOuSbAW4Zt4I3CZOh3j+bMax++6M37RWCpShCTdaapdm37y436QbtuB9K6ry7MLo
0HcqQksDm8tLmQqEenfhqZo10FiQj0v1ckvg3lzH4OIP5IM0zXkApnlX6aKuOBbC
XMkYSqdwK0A8QNrl051RCKE2CaYK3cnSN0z4+Vs=
-----END CERTIFICATE-----

View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIBmzCCAQQCAQAwWzELMAkGA1UEBhMCQ04xETAPBgNVBAgTCFpoZWppYW5nMREw
DwYDVQQHEwhIYW5nemhvdTESMBAGA1UEChMJTXkgQ2xpZW50MRIwEAYDVQQDEwls
b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJEUnBzXTTiyUmDb
yhkQoQ/yH1zTnuIk5Meg1Bp0fp1l4kwiizdPbZkk4YkTT/HXdTE6822Cqho+CwGE
VqWZyyd2AZmj87OGb4ZRCyyFzzjfEwdCTvyqZSUBoc1gvSGdEiaA4mXE87Y0XcMB
BasOrfmO76nuzyaXLT7xDjrB+Qw5AgMBAAGgADANBgkqhkiG9w0BAQUFAAOBgQAx
rsaWSV81/SCf+0af57Wr+BJfiGEutZpdmIe0ofPKfVfz7c8QKjqK+/xQb0INUaYd
MUPjuLfvp06iCWyDPsfhsBRZMSDfFZDp8bnoVloVbP+yLL2Gd+h/a5iYjKTJ2FEt
mDaoIXqbw7oHXXxfKKLP2iyUQCqbfJTC0XeJtFWJ3w==
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCRFJwc1004slJg28oZEKEP8h9c057iJOTHoNQadH6dZeJMIos3
T22ZJOGJE0/x13UxOvNtgqoaPgsBhFalmcsndgGZo/Ozhm+GUQsshc843xMHQk78
qmUlAaHNYL0hnRImgOJlxPO2NF3DAQWrDq35ju+p7s8mly0+8Q46wfkMOQIDAQAB
AoGAarOFvZB7st8zxxjfImAglOG2P0dE633G5Stb07kqBgkQzn35dcxtBt0hIveZ
LH0SLAr3Tetzv6kx3wO91j2uM1QURztULIcFaDrQyrBbAYoka2WDoxJCSRoGvb9X
7JoyuYtYvbctT8dvYF9mVttq/YdAjFfs7RHwMGSZUc9xkCECQQDA1NNdmsupDZrG
e6sBToEcNuLd/ahB77AS19dWt9WLGSDhG+/wj2bx9l73RTnadenjIPoRaY0RZu4u
fDNlKYErAkEAwJtQn4PSLZe3Rx/FfrGn4pxLFvL/6EgaPKxY1nNd55JY3x15L9A9
IjODD+CH+BYbYufHfI5n27QIVRDIpNAOKwJAb/2q3BxA1+fs0gWU5WdgmLBPxjnB
dLnt+qOcjuKphOWNMO/2xDGkyjYaJWXxGa2NrrnCQkaZBVhQUHMVrlUSjQJAeUhT
+F5VlwgWDN9gyWqtQPESB510r5vXiaUtO7zhwNRSygwRJ56FIGg3e2PzurCRBjLV
VwWFOL+hD4/GCKJKiQJAfQbp5pZ1Fni/YWo2gmuQi+9kMv3BKfpeHwNclPICY86c
JSAo2+e7Xwz+GHxW9Hqpuz4J1CKjFGS0VzZAFWBi2w==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRFJwc1004slJg28oZEKEP8h9c
057iJOTHoNQadH6dZeJMIos3T22ZJOGJE0/x13UxOvNtgqoaPgsBhFalmcsndgGZ
o/Ozhm+GUQsshc843xMHQk78qmUlAaHNYL0hnRImgOJlxPO2NF3DAQWrDq35ju+p
7s8mly0+8Q46wfkMOQIDAQAB
-----END PUBLIC KEY-----

View File

@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICKTCCAZICCQC8hk8d+ohSGzANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJD
TjERMA8GA1UECBMIWmhlamlhbmcxETAPBgNVBAcTCEhhbmd6aG91MQ4wDAYDVQQK
EwVNeSBDQTESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE3MDIwOTA3NTIzNloXDTE3
MDMxMTA3NTIzNlowWzELMAkGA1UEBhMCQ04xETAPBgNVBAgTCFpoZWppYW5nMREw
DwYDVQQHEwhIYW5nemhvdTESMBAGA1UEChMJTXkgU2VydmVyMRIwEAYDVQQDEwls
b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKg4oNy7liSNUU1T
gZQEEKPJ1znNgbCzbEJ/QlsKhLMzIjiv+xaTvYFffUcZw++NwsCwQUYsdAsmDwQT
4wdTr6JBKwYuKRnyL/l5N/h4VEmNh2MGz2NSqo66QNOiJMOYhmuxmcr08WXPr6Hp
A+KtpQgNt2NFB0nSbb/EvyJgSx85AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAHnKB
iH4Yy7P9dfgJ7/KAB3U15pFYVonPgiqCjVZLgF6rG1F0PNjRBaH24QLg1r/pzbYV
BwsM7WVslRiAx2xh4O3A67GukhPOVerNGcfiFeadqM2e9RVVtcLkwMMfRaL/4oRx
NrkkscP5NrD9lzbVGq9b+heQMYT3fPxokseNngc=
-----END CERTIFICATE-----

View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIBmzCCAQQCAQAwWzELMAkGA1UEBhMCQ04xETAPBgNVBAgTCFpoZWppYW5nMREw
DwYDVQQHEwhIYW5nemhvdTESMBAGA1UEChMJTXkgU2VydmVyMRIwEAYDVQQDEwls
b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKg4oNy7liSNUU1T
gZQEEKPJ1znNgbCzbEJ/QlsKhLMzIjiv+xaTvYFffUcZw++NwsCwQUYsdAsmDwQT
4wdTr6JBKwYuKRnyL/l5N/h4VEmNh2MGz2NSqo66QNOiJMOYhmuxmcr08WXPr6Hp
A+KtpQgNt2NFB0nSbb/EvyJgSx85AgMBAAGgADANBgkqhkiG9w0BAQUFAAOBgQA6
hlKHAfMWwwyqdqsMPd+Q4LetmER+ARnMZTOMSMp1iFXEdTIZwA+WHfxdN+KJ4gnp
3QWpoG+q4O2tyMZQDB9wSAY7LbFyHjzpqq1JJXL2Qpa71NqE0JRZEToAxuyrGf0n
NCpZp0vHFERhgntLkNSM9sMFCWuB6dB1YfeCkTWCeA==
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCoOKDcu5YkjVFNU4GUBBCjydc5zYGws2xCf0JbCoSzMyI4r/sW
k72BX31HGcPvjcLAsEFGLHQLJg8EE+MHU6+iQSsGLikZ8i/5eTf4eFRJjYdjBs9j
UqqOukDToiTDmIZrsZnK9PFlz6+h6QPiraUIDbdjRQdJ0m2/xL8iYEsfOQIDAQAB
AoGAPmbbTWaMuLxvd2bNv5GOdqOuIjQYsuqr8zLv84PAXBVQ0YR+eQ6PEsnQWCq3
o0qL/xyi6hwdY/FXSqTx58rkcIsO7BRlmaQ7uqEgMd52UUej/xAka8mFVJbjAjPR
gB2mGaoO9IiPYFwrjoDA5v/lFq62SLZ81nvOOwbjZxXW3TECQQDS1yGKPuvxOV/w
BVCYwhSALMMXBxhAVi4bDtft6dMqXtOourBpUS9zvGx2GTct4hpzVFGkVt7VONbH
/oGUOKytAkEAzECW/LV5v9R7ufcTbAgbML4+Yh/38lvPg2Oh2f6k1RMerszRJ6nZ
K+wwRnmT+gmPCIiKmebhZ7OkmlUiz6ciPQJBAKijX/VWfJt127F8XsnAOmuG4ggS
KaiUBc6oobdu1fLG5B7KK/4g7IZyyIHxizwM5EEoySBcR2FeVBSlEXm/lwUCQQCC
eFO6MxYFQm6SONBwNrFfrnZc6bzRVHI2pILzpCSYcvEriWulIWq3EtU3f1vV4Rs7
wTR/4KplOqxPZUiqSkGlAkAy5HpRgBjCG57vHpwIv8jZm3g0/8Kqle5dMp8o8IVI
2gh6YbBt2xIZCgGKKK6VUYz7PdGyEZ+I/41iIeLzftek
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCoOKDcu5YkjVFNU4GUBBCjydc5
zYGws2xCf0JbCoSzMyI4r/sWk72BX31HGcPvjcLAsEFGLHQLJg8EE+MHU6+iQSsG
LikZ8i/5eTf4eFRJjYdjBs9jUqqOukDToiTDmIZrsZnK9PFlz6+h6QPiraUIDbdj
RQdJ0m2/xL8iYEsfOQIDAQAB
-----END PUBLIC KEY-----

View File

@ -0,0 +1,8 @@
<?php
require_once __DIR__ . "/http_server.php";
$host = isset($argv[1]) ? $argv[1] : HTTP_SERVER_HOST;
$port = isset($argv[2]) ? $argv[2] : HTTP_SERVER_PORT;
(new HttpServer($host, $port, false))->start();

View File

@ -0,0 +1,30 @@
<?php
require_once __DIR__ . "/http_server.php";
/*
class swoole_http_server extends swoole_server
{
public swoole_function on($name, $cb) {} // 与 tcp swoole_server 的on接受的eventname 不同
}
class swoole_http_response
{
public swoole_function cookie() {}
public swoole_function rawcookie() {}
public swoole_function status() {}
public swoole_function gzip() {}
public swoole_function header() {}
public swoole_function write() {}
public swoole_function end() {}
public swoole_function sendfile() {}
}
class swoole_http_request
{
public swoole_function rawcontent() {}
}
*/
$host = isset($argv[1]) ? $argv[1] : HTTP_SERVER_HOST;
$port = isset($argv[2]) ? $argv[2] : HTTP_SERVER_PORT;
(new HttpServer($host, $port, true))->start();

View File

@ -0,0 +1,67 @@
<?php
$pdo = new \PDO('swoole_mysql:dbname=db_koudaitong;host=127.0.0.1;port=3007', 'user_koudaitong', 'ocfLsVO7l2B3TMOPmpSX');
// 1
//$stmt = $pdo->prepare("select * from attachment where mp_id = :mp_id LIMIT 10");
//$stmt->bindValue(":mp_id", 1, \PDO::PARAM_INT);
// 2
$stmt = $pdo->prepare("select * from attachment where mp_id = ? LIMIT 10");
$stmt->bindValue(1, 1, \PDO::PARAM_INT);
$stmt->execute();
$r = $stmt->fetchAll(\PDO::FETCH_ASSOC);
var_dump($r);
$mysqli = new \mysqli();
$mysqli->connect('127.0.0.1', 'user_koudaitong', 'ocfLsVO7l2B3TMOPmpSX', 'db_koudaitong', '3007');
if ($mysqli->connect_errno) {
printf("Connect failed: [errno=%d]%s\n", $mysqli->connect_errno, $mysqli->connect_error);
exit();
}
$stmt = $mysqli->prepare("select * from attachment where mp_id = ? LIMIT 10");
if ($stmt) {
$kdt_id = 1;
$stmt->bind_param("i", $kdt_id);
$stmt->execute();
$stmt->bind_result($r);
$stmt->fetch();
var_dump($r);
$stmt->close();
} else {
printf("Prepare failed: [errno=%d]%s\n", $mysqli->errno, $mysqli->error);
}
$mysqli->close();
//require_once __DIR__ . "/swoole_mysql_init.php";
// sql syntax error
//$ret = $link->query("select");
//echo $link->error, "\n"; // You have an error in your SQL syntax; check the manual that corresponds to your MySQL swoole_server version for the right syntax to use near '' at line 1
//echo $link->errno; //1064
//exit;
// select
//$ret = $link->query("select 1, 1, 1");
// var_dump(mysqli_fetch_field($ret));
// var_dump(mysqli_fetch_assoc($ret));
// var_dump(mysqli_fetch_all($ret));
//exit;
// insert
//$ret = $link->query("insert into ad (`kdt_id`, `num`, `data`, `valid`, `created_time`, `update_time`) VALUES (99999, 1, 'data', 1, 0, 0)");
//var_dump($ret);
//var_dump($link->insert_id);
//exit;

View File

@ -0,0 +1,50 @@
<?php
require_once __DIR__ . "/swoole_mysql_init.php";
$sql = "select 1";
$bind = [];
$onQuery = function($mysql_result, $result) {
var_dump($result);
swoole_event_exit();
fprintf(STDERR, "SUCCESS");
};
$swoole_mysql = new \swoole_mysql();
$swoole_mysql->on("connect", function(\swoole_mysql $swoole_mysql) use($sql, $bind, $onQuery, $swoole_mysql) {
// $swoole_mysql->query($sql, $bind, swoole_function(\swoole_mysql $swoole_mysql, $result) use($onQuery) {
// $onQuery($swoole_mysql, $result);
// $swoole_mysql->close();
// });
});
$swoole_mysql->on("error", function(\swoole_mysql $swoole_mysql) use($onQuery, $swoole_mysql) {
$onQuery($swoole_mysql, "connection error");
});
$swoole_mysql->on("close", function() {
echo "closed\n";
});
$swoole_mysql->connect([
"host" => MYSQL_SERVER_HOST,
"port" => MYSQL_SERVER_PORT,
"user" => MYSQL_SERVER_USER,
"password" => MYSQL_SERVER_PWD,
"database" => MYSQL_SERVER_DB,
"charset" => "utf8mb4",
]);
// 未连上 直接 调用query
$r = $swoole_mysql->query($sql, $bind, function(\swoole_mysql $swoole_mysql, $result) use($onQuery) {
var_dump("query cb");
// TODO error error_no
$onQuery($swoole_mysql, $result);
// $swoole_mysql->close();
});
// 此处返回true 不符合预期
var_dump($r);

View File

@ -0,0 +1,21 @@
<?php
$swoole_mysql = new \swoole_mysql();
$swoole_mysql->on("close", function ()
{
echo "closed\n";
swoole_event_exit();
});
$r = $swoole_mysql->connect([
"host" => "11.11.11.11",
"port" => 9000,
"user" => "root",
"password" => "admin",
"database" => "test",
"charset" => "utf8mb4",
'timeout' => 1.0,
], function (\swoole_mysql $swoole_mysql, $result)
{
assert($result === false);
});

View File

@ -0,0 +1,63 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
$onQuery = function ($swoole_mysql, $result)
{
assert($swoole_mysql->errno === 0);
$swoole_mysql->query("select 1", function ($swoole_mysql, $result)
{
assert($swoole_mysql->errno === 0);
echo "SUCCESS\n";
swoole_event_exit();
});
};
$sql = "show tables";
$swoole_mysql = new \swoole_mysql();
$swoole_mysql->on("close", function ()
{
echo "closed\n";
});
$onConnect = function (\swoole_mysql $swoole_mysql, $result) use ($sql, $onQuery)
{
if ($result)
{
$swoole_mysql->query_timeout = swoole_timer_after(1000, function () use ($onQuery, $swoole_mysql)
{
$onQuery($swoole_mysql, "query timeout");
});
$swoole_mysql->query($sql, function (\swoole_mysql $swoole_mysql, $result) use ($onQuery)
{
swoole_timer_clear($swoole_mysql->query_timeout);
$onQuery($swoole_mysql, $result);
});
}
else
{
echo "connect to swoole_mysql swoole_server[{$swoole_mysql->serverInfo['host']}:{$swoole_mysql->serverInfo['port']}] error [errno=$swoole_mysql->connect_errno, error=$swoole_mysql->connect_error]";
}
};
$r = $swoole_mysql->connect([
"host" => MYSQL_SERVER_HOST,
"port" => MYSQL_SERVER_PORT,
"user" => MYSQL_SERVER_USER,
"password" => MYSQL_SERVER_PWD,
"database" => MYSQL_SERVER_DB,
"charset" => "utf8mb4",
], $onConnect);
assert($r);
$r = @$swoole_mysql->connect([
"host" => MYSQL_SERVER_HOST,
"port" => MYSQL_SERVER_PORT,
"user" => MYSQL_SERVER_USER,
"password" => MYSQL_SERVER_PWD,
"database" => MYSQL_SERVER_DB,
"charset" => "utf8mb4",
], $onConnect);
assert($r === false);

View File

@ -0,0 +1,34 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
function swoole_mysql_query($sql, callable $onQuery)
{
$mysql = new \swoole_mysql();
$mysql->on("close", function ()
{
echo "closed\n";
});
$mysql->connect([
"host" => MYSQL_SERVER_HOST,
"port" => MYSQL_SERVER_PORT,
"user" => MYSQL_SERVER_USER,
"password" => MYSQL_SERVER_PWD,
"database" => MYSQL_SERVER_DB,
"charset" => "utf8mb4",
], function (\swoole_mysql $mysql, $result) use ($sql, $onQuery)
{
if ($result)
{
$mysql->query($sql, function (\swoole_mysql $swoole_mysql, $result) use ($onQuery)
{
$onQuery($swoole_mysql, $result);
});
}
else
{
echo "connect error [errno=$mysql->connect_errno, error=$mysql->connect_error]";
}
});
}

View File

@ -0,0 +1,57 @@
<?php
// 轻微内存泄漏
//while (true) {
// echo memory_get_usage(), "\n";
// $pdo = new \PDO('swoole_mysql:dbname=test;host=127.0.0.1;port=3306', 'root', '123456');
// $stmt = $pdo->prepare("select * from test");
// $stmt->execute();
// $r = $stmt->fetchAll(\PDO::FETCH_ASSOC);
// // var_dump(count($r));
//}
$sql = "select * from component_v2";
define("MYSQL_SERVER_HOST", "127.0.0.1");
define("MYSQL_SERVER_PORT", 3306);
define("MYSQL_SERVER_USER", "test_database");
define("MYSQL_SERVER_PWD", "test_database");
define("MYSQL_SERVER_DB", "test_database");
//$sql = "select * from test";
//define("MYSQL_SERVER_HOST", "127.0.0.1");
//define("MYSQL_SERVER_PORT", 3306);
//define("MYSQL_SERVER_USER", "root");
//define("MYSQL_SERVER_PWD", "123456");
//define("MYSQL_SERVER_DB", "test");
class Callback
{
public $sql;
public $result;
public function __construct($sql)
{
$this->sql = $sql;
}
public function __invoke($mysql, $result)
{
echo memory_get_usage(), "\n";
$this->result = $result;
$mysql->query($this->sql, new Callback($this->sql));
}
}
$swoole_mysql = new \swoole_mysql();
$swoole_mysql->on("close", function() { echo "closed\n"; });
$swoole_mysql->connect([
"host" => MYSQL_SERVER_HOST,
"port" => MYSQL_SERVER_PORT,
"user" => MYSQL_SERVER_USER,
"password" => MYSQL_SERVER_PWD,
"database" => MYSQL_SERVER_DB,
"charset" => "utf8mb4",
], function(\swoole_mysql $mysql) use($sql) {
$mysql->query($sql, new Callback($sql));
});

View File

@ -0,0 +1,13 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
$swoole_mysql = new \swoole_mysql();
$swoole_mysql->connect([
"host" => MYSQL_SERVER_HOST,
"port" => MYSQL_SERVER_PORT,
"user" => MYSQL_SERVER_USER,
"password" => MYSQL_SERVER_PWD,
"database" => MYSQL_SERVER_DB,
"charset" => "utf8mb4",
], null);

View File

@ -0,0 +1,16 @@
<?php
require_once __DIR__ . "/swoole_mysql_init.php";
$n = 1024 * 1024;
$fields = implode(", ", range(0, $n - 1));
swoole_mysql_query("select $fields", function($swoole_mysql, $result) {
if ($swoole_mysql->errno === 0) {
fprintf(STDERR, "SUCCESS");
} else {
fprintf(STDERR, "ERROR");
}
swoole_event_exit();
});

View File

@ -0,0 +1,27 @@
<?php
require_once __DIR__ . "/swoole_mysql_init.php";
//$pdo = new \PDO("swoole_mysql:dbname=showcase;host=127.0.0.1", "test_database", "test_database");
//$ret = $pdo->query("select 1, 1");
//var_dump($ret->fetchAll());
//exit;
//$link = new \mysqli();
//swoole_mysql_query();
//$link->connect(MYSQL_SERVER_HOST, MYSQL_SERVER_USER, MYSQL_SERVER_PWD, MYSQL_SERVER_DB, MYSQL_SERVER_PORT);
//$ret = $link->query("select 1, 1");
//$ret = $link->query("select * from ad");
//var_dump($ret);
//var_dump(mysqli_fetch_assoc($ret));
//var_dump(mysqli_fetch_field($ret));
//var_dump(mysqli_fetch_all($ret));
//exit;
swoole_mysql_query("select 1, 1", function($swoole_mysql, $result) {
assert($swoole_mysql->errno === 0);
var_dump($result);
assert(count($result[0]) === 2);
swoole_event_exit();
});

View File

@ -0,0 +1,46 @@
<?php
require_once __DIR__ . "/swoole_mysql_init.php";
function query($swoole_mysql, $dep = 0)
{
$sql = "select 1";
$swoole_mysql->query($sql, function(\swoole_mysql $swoole_mysql, $result) use($dep) {
// echo ".\n";
if ($dep > 20) {
fprintf(STDERR, "SUCCESS\n");
swoole_event_exit();
} else {
if ($swoole_mysql->errno !== 0) {
fprintf(STDERR, "FAIL");
swoole_event_exit();
} else {
query($swoole_mysql, ++$dep);
}
}
});
}
$swoole_mysql = new \swoole_mysql();
$swoole_mysql->on("close", function() {
echo "closed\n";
});
$swoole_mysql->conn_timeout = swoole_timer_after(1000, function() {
echo "connecte timeout\n\n\n";
});
$swoole_mysql->connect([
"host" => MYSQL_SERVER_HOST,
"port" => MYSQL_SERVER_PORT,
"user" => MYSQL_SERVER_USER,
"password" => MYSQL_SERVER_PWD,
"database" => MYSQL_SERVER_DB,
"charset" => "utf8mb4",
], function(\swoole_mysql $swoole_mysql) {
assert($swoole_mysql->errno === 0);
swoole_timer_clear($swoole_mysql->conn_timeout);
query($swoole_mysql);
});

View File

@ -0,0 +1,26 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
$i = 10000;
$start = $end = 0;
while($i--) {
if ($i == 99) {
$start = memory_get_usage();
}
// 不应该在构造函数加引用计数
$swoole_mysql = new \swoole_mysql();
// xdebug_debug_zval("swoole_mysql"); // 2
if ($i == 1) {
$end = memory_get_usage();
}
}
if (($end - $start) < 1000) {
fprintf(STDERR, "SUCCESS");
} else {
fprintf(STDERR, "FAIL");
}
swoole_event_exit();

View File

@ -0,0 +1,12 @@
<?php
require_once __DIR__ . "/swoole_mysql_init.php";
swoole_mysql_query("select", function($mysql_result, $result) {
if ($mysql_result->errno === 1064) {
fprintf(STDERR, "SUCCESS");
} else {
fprintf(STDERR, "FAIL");
}
swoole_event_exit();
});

View File

@ -0,0 +1,15 @@
<?php
$redis = new swoole_redis();
$redis->on("close", function (){
echo "closed\n";
});
$redis->on("message", function (){
echo "message\n";
});
$result = $redis->connect("192.1.1.1", 9000, function ($redis, $result)
{
assert($redis->errCode == SOCKET_ETIMEDOUT);
assert($result === false);
});

View File

@ -0,0 +1,61 @@
<?php
function get(\swoole_redis $redis)
{
// TODO 为什么需要timer否则call返回false TIMER ???
swoole_timer_after(1, function() use($redis) {
$r = $redis->get("HELLO", function(\swoole_redis $redis, $result) {
var_dump($result);
get($redis);
});
assert($r);
$redis->close();
test();
});
}
function test()
{
$redis = new \swoole_redis();
$redis->on("close", function(\swoole_redis $redis) {
echo "close\n\n";
test();
// 死循环
// $swoole_redis->close();
});
$redis->connect("127.0.0.1", 6379, function(\swoole_redis $redis, $connected) {
assert($connected);
// get($swoole_redis);
$redis->get("HELLO", function(\swoole_redis $redis, $result) {});
});
}
test();
return;
function test1() {
$redis = new \swoole_redis();
$redis->on("close", function() { echo "close"; });
$redis->connect("127.0.0.1", 6379, function(\swoole_redis $redis, $connected) {
assert($connected);
swoole_timer_after(1, function() use($redis) {
$r = $redis->get("HELLO", function(\swoole_redis $redis, $result) {
var_dump($redis);
var_dump($result);
test();
});
assert($r);
swoole_timer_after(1, function() use($redis) {
// $r = $swoole_redis->close();
// var_dump($r);
// $swoole_redis->close();
});
});
});
}
test1();

View File

@ -0,0 +1,54 @@
<?php
(new FakeRedisServer())->start();
class FakeRedisServer
{
public $swooleServer;
public function __construct()
{
$this->swooleServer = new \swoole_server("0.0.0.0", 6379, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$this->swooleServer->set(["worker_num" => 1]);
}
public function start()
{
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('receive', [$this, 'onReceive']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->start();
}
public function onClose() {}
public function onStart(swoole_server $swooleServer) {}
public function onShutdown(swoole_server $swooleServer) {}
public function onWorkerStart(swoole_server $swooleServer, $workerId) {}
public function onWorkerStop(swoole_server $swooleServer, $workerId) {}
public function onWorkerError(swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo) {}
public function onConnect(swoole_server $swooleServer, $fd) {
// $swooleServer->close($fd);
}
public function onReceive(swoole_server $swooleServer, $fd, $fromId, $data)
{
$swooleServer->send($fd, "\0");
return;
$swooleServer->send($fd, "$-1\r\n");
echo $data;
swoole_timer_after(1000, function() use($swooleServer, $fd) {
$swooleServer->close($fd);
});
}
}

View File

@ -0,0 +1,13 @@
<?php
$host = isset($argv[1]) ? $argv[1] : HTTP_SERVER_HOST;
$port = isset($argv[2]) ? $argv[2] : HTTP_SERVER_PORT;
$swoole = new swoole_server($host, $port);
$swoole->on("connect", function ($server, $fd) {
});
$swoole->on("receive", function ($server, $fd, $from_id, $data) {
});
$swoole->start();

View File

@ -0,0 +1,67 @@
<?php
define("REDIS_SERVER_HOST", "127.0.0.1");
define("REDIS_SERVER_PORT", 6379);
$redis = new \swoole_redis();
$redis->on("close", function() { echo "close"; });
// !!!! For SUBSCRIBE
$redis->on("message", function() { var_dump(func_get_args()); });
$redis->connect(REDIS_SERVER_HOST, REDIS_SERVER_PORT, function(\swoole_redis $redis, $connected) {
if ($connected === false) {
fputs(STDERR, "ERROR:$redis->errMsg($redis->errCode)\n");
echo "connected fail";
return;
}
echo "connected\n";
$luaScript = <<<LUA
error scripr
LUA;
$redis->eval($luaScript, 0, function(\swoole_redis $redis, $result) {
if ($result === false) {
// TODO WTF ? 错误信息呢?!
// 这里的errMsg 与 errCode是socket的
// 那redis原生的呢
// 抓包可以看到错误返回信息
fputs(STDERR, "ERROR:$redis->errMsg($redis->errCode)\n");
} else {
var_dump($result);
}
$redis->close();
});
return;
/**
* evalsha
* SCRIPT FLUSH :清除所有脚本缓存
* SCRIPT EXISTS :根据给定的脚本校验和,检查指定的脚本是否存在于脚本缓存
* SCRIPT LOAD :将一个脚本装入脚本缓存,但并不立即运行它
* SCRIPT KILL :杀死当前正在运行的脚本
*/
$luaScript = <<<LUA
return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}
LUA;
$keyNum = 2;
$key1 = "key1";
$key2 = "key2";
$val1 = "first";
$val2 = "second";
$r = $redis->eval($luaScript, $keyNum, $key1, $key2, $val1, $val2, function(\swoole_redis $redis, $result) {
if ($result === false) {
var_dump($redis);
redis_error($redis);
// WTF
// -ERR Error compiling script (new swoole_function): user_script:1: unfinished string near '<eof>'
} else {
var_dump($result);
}
$redis->close();
});
assert($r === true);
});

View File

@ -0,0 +1,43 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
class Obj
{
}
$redis = new swoole_redis();
$redis->on("close", function ()
{
echo "close";
});
$redis->on("message", function ()
{
var_dump(func_get_args());
});
define('REDIS_TEST_KEY', "swoole:test:key_" . md5(microtime()));
define('REDIS_TEST_VALUE', RandStr::gen(128, RandStr::ALPHA | RandStr::NUM | RandStr::CHINESE));
// $swoole_redis->connect(REDIS_SERVER_PATH, false, swoole_function() {}); TODO
$redis->connect(REDIS_SERVER_HOST, REDIS_SERVER_PORT, function (\swoole_redis $redis)
{
$redis->get(REDIS_TEST_KEY, function (\swoole_redis $redis, $result)
{
assert($result === null);
$redis->set(REDIS_TEST_KEY, REDIS_TEST_VALUE, function (\swoole_redis $redis, $result)
{
assert($result === 'OK');
$redis->get(REDIS_TEST_KEY, function (\swoole_redis $redis, $result)
{
assert($result === REDIS_TEST_VALUE);
$redis->del(REDIS_TEST_KEY, function (\swoole_redis $redis, $result)
{
assert($result === 1);
$redis->close();
});
});
});
});
});

View File

@ -0,0 +1,101 @@
<?php
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| Copyright (c) 2012-2017 The Swoole Group |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
abstract class TestServer
{
protected $index = array();
protected $recv_bytes = 0;
protected $count = 0;
protected $show_lost_package = false;
const PKG_NUM = 100000;
const LEN_MIN = 0;
const LEN_MAX = 200;
/**
* @var swoole_server
*/
protected $serv;
abstract function onReceive($serv, $fd, $reactor_id, $data);
function __construct($base = false)
{
$mode = $base ? SWOOLE_BASE : SWOOLE_PROCESS;
$serv = new swoole_server("127.0.0.1", 9501, $mode);
$serv->on('Connect', [$this, 'onConnect']);
$serv->on('receive', [$this, '_receive']);
$serv->on('workerStart', [$this, 'onWorkerStart']);
$serv->on('Close', [$this, 'onClose']);
$this->serv = $serv;
}
function onConnect($serv, $fd, $from_id)
{
}
function _receive($serv, $fd, $from_id, $data)
{
$this->count++;
$this->recv_bytes += strlen($data);
$this->onReceive($serv, $fd, $from_id, $data);
if ($this->count == self::PKG_NUM)
{
$serv->send($fd, "end\n");
}
}
function onClose($serv, $fd, $from_id)
{
echo "Total count={$this->count}, bytes={$this->recv_bytes}\n";
if ($this->show_lost_package)
{
for ($i = 0; $i < self::PKG_NUM; $i++)
{
if (!isset($this->index[$i]))
{
echo "lost package#$i\n";
}
}
}
$this->count = $this->recv_bytes = 0;
unset($this->index);
$this->index = array();
}
function set($conf)
{
$this->serv->set($conf);
}
function start()
{
$this->serv->start();
}
function onWorkerStart($serv, $id)
{
//sleep(1);
}
static function random()
{
return rand(self::LEN_MIN, self::LEN_MAX);
}
}

View File

@ -0,0 +1,16 @@
[2017-01-09 20:48:45 *7139.0] WARNING swServer_tcp_deny_exit: swServer_tcp_deny_exit
[2017-01-09 20:48:45 *7140.1] WARNING swServer_tcp_deny_exit: swServer_tcp_deny_exit
[2017-01-09 20:48:45 #7136.0] WARNING swReactorThread_onPipeReceive: [Master] set worker idle.[work_id=0]
[2017-01-09 20:48:45 #7136.0] WARNING swReactorThread_onPipeReceive: [Master] set worker idle.[work_id=1]
[2017-01-09 20:48:48 #7136.0] WARNING swServer_signal_hanlder: Fatal Error: manager process exit. status=1, signal=23.
[2017-01-09 20:48:48 *7140.1] ERROR swFactoryProcess_finish (ERROR 1004): send 1024 byte failed, because session#1 is closed.
[2017-01-09 20:49:14 *7149.0] WARNING swServer_tcp_deny_exit: swServer_tcp_deny_exit
[2017-01-09 20:49:14 @7146.0] WARNING swReactorThread_onPipeReceive: [Master] set worker idle.[work_id=0]
[2017-01-09 20:49:14 *7150.1] WARNING swServer_tcp_deny_exit: swServer_tcp_deny_exit
[2017-01-09 20:49:14 #7146.0] WARNING swReactorThread_onPipeReceive: [Master] set worker idle.[work_id=1]
[2017-01-09 20:49:16 #7146.0] WARNING swServer_signal_hanlder: Fatal Error: manager process exit. status=24, signal=38.
[2017-01-09 20:50:23 *7158.1] WARNING swServer_tcp_deny_exit: swServer_tcp_deny_exit
[2017-01-09 20:50:23 *7157.0] WARNING swServer_tcp_deny_exit: swServer_tcp_deny_exit
[2017-01-09 20:50:23 #7154.0] WARNING swReactorThread_onPipeReceive: [Master] set worker idle.[work_id=1]
[2017-01-09 20:50:23 #7154.0] WARNING swReactorThread_onPipeReceive: [Master] set worker idle.[work_id=0]
[2017-01-09 20:50:24 #7154.0] WARNING swServer_signal_hanlder: Fatal Error: manager process exit. status=49, signal=82.

View File

@ -0,0 +1,110 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//(new OpcodeServer("127.0.0.1", 9999, 9998, 9997))->start(PHP_INT_MAX);
$host = isset($argv[1]) ? $argv[1] : null;
$port = isset($argv[2]) ? $argv[2] : null;
$port1 = isset($argv[3]) ? $argv[3] : null;
$port2 = isset($argv[4]) ? $argv[4] : null;
(new OpcodeServer($host, $port, $port1, $port2))->start();
class OpcodeServer
{
/**
* @var \swoole_server
*/
public $swooleServer;
public function __construct($host, $port, $port1, $port2)
{
$this->swooleServer = new \swoole_server($host, $port, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$this->swooleServer->set([
'dispatch_mode' => 3,
'worker_num' => 2,
'open_eof_split' => true,
'package_eof' => "\r\n",
]);
$this->swooleServer->on("receive", function(\swoole_server $server, $fd, $fromReactorId, $recv) use($port) {
assert(intval($recv) === $port);
$r = $server->send($fd, opcode_encode("return", $port));
assert($r !== false);
});
$serv1 = $this->swooleServer->listen(TCP_SERVER_HOST, $port1, SWOOLE_SOCK_TCP);
assert($serv1 !== false);
$serv1->set([
'open_eof_split' => true,
'package_eof' => "\r",
]);
$serv1->on("receive", function(\swoole_server $server, $fd, $fromReactorId, $recv) use($port1) {
assert(intval($recv) === $port1);
$r = $server->send($fd, opcode_encode("return", $port1));
assert($r !== false);
});
$serv2 = $this->swooleServer->listen(TCP_SERVER_HOST, $port2, SWOOLE_SOCK_TCP);
assert($serv2 !== false);
$serv2->set([
'open_eof_split' => true,
'package_eof' => "\n",
]);
$serv2->on("receive", function(\swoole_server $server, $fd, $fromReactorId, $recv) use($port2) {
assert(intval($recv) === $port2);
$r = $server->send($fd, opcode_encode("return", $port2));
assert($r !== false);
});
}
public function start($lifetime = 1000)
{
$this->lifetime = $lifetime;
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->start();
}
public function onConnect() { }
public function onClose() { }
public function onStart(\swoole_server $swooleServer) { }
public function onShutdown(\swoole_server $swooleServer) { }
public function onWorkerStart(\swoole_server $swooleServer, $workerId)
{
if ($workerId === 0) {
swoole_timer_after($this->lifetime, function() {
$this->swooleServer->shutdown();
kill_self_and_descendant(getmypid());
/*
\swoole_process::signal(SIGTERM, swoole_function() {
$this->swooleServer->shutdown();
});
\swoole_process::kill(0, SIGTERM);
*/
});
}
}
public function onWorkerStop(\swoole_server $swooleServer, $workerId) { }
public function onWorkerError(\swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo) { }
}

View File

@ -0,0 +1,183 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
// (new OpcodeServer("127.0.0.1", 9999))->start(PHP_INT_MAX);
$host = isset($argv[1]) ? $argv[1] : HTTP_SERVER_HOST;
$port = isset($argv[2]) ? $argv[2] : HTTP_SERVER_PORT;
$port1 = isset($argv[3]) ? $argv[3] : null;
$port2 = isset($argv[4]) ? $argv[4] : null;
(new OpcodeServer($host, $port, $port1, $port2))->start();
class OpcodeServer
{
/**
* @var \swoole_server
*/
public $swooleServer;
public function __construct($host, $port, $port1 = null, $port2 = null)
{
$this->swooleServer = new \swoole_server($host, $port, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$this->swooleServer->set([
'dispatch_mode' => 3,
'worker_num' => 2,
'task_worker_num' => 2,
'open_length_check' => 1,
'package_length_type' => 'N',
'package_length_offset' => 0,
'package_body_offset' => 0,
"heartbeat_idle_time"=> 20
]);
if ($port1) {
$serv1 = $this->swooleServer->addListener(TCP_SERVER_HOST, $port1, SWOOLE_SOCK_TCP);
assert($serv1 !== false);
}
if ($port2) {
$serv2 = $this->swooleServer->addListener(TCP_SERVER_HOST, $port2, SWOOLE_SOCK_TCP);
assert($serv2 !== false);
}
}
public function start($lifetime = 1000)
{
$this->lifetime = $lifetime;
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('receive', [$this, 'onReceive']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->on('task', [$this, 'onTask']);
$this->swooleServer->on('finish', [$this, 'onFinish']);
$this->swooleServer->on('pipeMessage', [$this, 'onPipeMessage']);
$this->swooleServer->on('packet', [$this, 'onPacket']);
/*
$proc = new \swoole_process(swoole_function(\swoole_process $proc) use($i) {
var_dump($this->swooleServer->id);
sleep(10000);
$r = $this->swooleServer->addProcess($proc);
var_dump($r);
$proc->freeQueue();
});
$proc->useQueue();
// $proc->start();
$proc1 = new \swoole_process(swoole_function(\swoole_process $proc) use($i) {
var_dump($this->swooleServer->id);
sleep(1000);
});
$proc2 = new \swoole_process(swoole_function(\swoole_process $proc) {
var_dump($this->swooleServer->id);
sleep(1000);
});
$r = $this->swooleServer->addProcess($proc);
$r = $this->swooleServer->addProcess($proc1);
$r = $this->swooleServer->addProcess($proc2);
var_dump($this->swooleServer->id);
*/
$this->swooleServer->start();
}
public function onConnect() { }
public function onClose() { }
public function onStart(\swoole_server $swooleServer) { }
public function onShutdown(\swoole_server $swooleServer) { }
public function onWorkerStart(\swoole_server $swooleServer, $workerId)
{
if ($workerId === 0) {
swoole_timer_after($this->lifetime, function() {
$this->swooleServer->shutdown();
kill_self_and_descendant(getmypid());
/*
\swoole_process::signal(SIGTERM, swoole_function() {
$this->swooleServer->shutdown();
});
\swoole_process::kill(0, SIGTERM);
*/
});
}
}
public function onWorkerStop(\swoole_server $swooleServer, $workerId) { }
public function onWorkerError(\swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo) { }
public function onReceive(\swoole_server $swooleServer, $fd, $fromReactorId, $recv)
{
list($op, $args) = opcode_decode($recv);
switch($op) {
case "sendMessage":
list($msg, $toWorkerId) = $args;
$r = $swooleServer->sendMessage(json_encode([
"fd" => $fd,
"msg" => $msg,
]), $toWorkerId);
assert($r);
return;
case "sendfile":
$len = filesize(__FILE__);
$r = $swooleServer->send($fd, pack("N", $len + 4));
assert($r !== false);
$r =$swooleServer->sendfile($fd, __FILE__);
assert($r !== false);
return;
default:
if (method_exists($swooleServer, $op)) {
$r = call_user_func_array([$swooleServer, $op], $args);
if (is_resource($r)) {
$r = true;
}
$r = $swooleServer->send($fd, opcode_encode("return", $r));
assert($r !== false);
return;
} else {
}
}
}
public function onTask(\swoole_server $swooleServer, $taskId, $fromWorkerId, $recv)
{
$recv = json_decode($recv);
assert(json_last_error() === JSON_ERROR_NONE);
return json_encode($recv);
}
public function onFinish(\swoole_server $swooleServer, $taskId, $recv)
{
$recv = json_decode($recv);
assert(json_last_error() === JSON_ERROR_NONE);
assert(isset($recv["fd"]) && isset($recv["data"]));
$this->swooleServer->send($recv["fd"], opcode_encode("return", $recv["data"]));
}
public function onPipeMessage(\swoole_server $swooleServer, $fromWorkerId, $recv)
{
$recv = json_decode($recv, true);
assert(json_last_error() === JSON_ERROR_NONE);
assert(isset($recv["fd"]) && isset($recv["msg"]));
$this->swooleServer->send($recv["fd"], opcode_encode("return", $recv["msg"]));
}
public function onPacket(\swoole_server $swooleServer, $data, array $clientInfo)
{
}
}

View File

@ -0,0 +1,19 @@
<?php
ini_set("memory_limit", "1024m");
function reconn() {
echo "Reconnect\n";
$cli = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$cli->on("connect", function(swoole_client $cli) {
// client 发送 大包数据
$cli->send(str_repeat("\0", 1024 * 1024 * 1.9));
});
$cli->on("receive", function(swoole_client $cli, $data) {
$cli->send($data);
});
$cli->on("error", function(swoole_client $cli) { echo "error\n"; });
$cli->on("close", function(swoole_client $cli) { echo "close\n"; reconn(); });
$cli->connect("127.0.0.1", 9001);
}
reconn();

View File

@ -0,0 +1,106 @@
<?php
function debug_log($str, $handle = STDERR)
{
if ($handle === STDERR) {
$tpl = "\033[31m[%d %s] %s\033[0m\n";
} else {
$tpl = "[%d %s] %s\n";
}
if (is_resource($handle)) {
fprintf($handle, $tpl, posix_getpid(), date("Y-m-d H:i:s", time()), $str);
} else {
printf($tpl, posix_getpid(), date("Y-m-d H:i:s", time()), $str);
}
}
(new TcpServer())->start();
class TcpServer
{
/**
* @var \swoole_server
*/
public $swooleServer;
public function __construct()
{
$this->swooleServer = new \swoole_server("127.0.0.1", 9001, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$this->swooleServer->set([
// "buffer_output_size" => 1024 * 1024 * 1024, // 输出限制
'max_connection' => 10240,
'pipe_buffer_size' => 1024 * 1024 * 2,
// 'pipe_buffer_size' => 1024,
'dispatch_mode' => 3,
'open_tcp_nodelay' => 1,
'open_cpu_affinity' => 1,
'daemonize' => 0,
'reactor_num' => 1,
'worker_num' => 2,
'max_request' => 100000,
]);
}
public function start()
{
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('receive', [$this, 'onReceive']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->start();
}
public function onConnect()
{
debug_log("connecting ......");
}
public function onClose()
{
debug_log("closing .....");
}
public function onStart(swoole_server $swooleServer)
{
debug_log("swoole_server starting .....");
}
public function onShutdown(swoole_server $swooleServer)
{
debug_log("swoole_server shutdown .....");
}
public function onWorkerStart(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId starting .....");
}
public function onWorkerStop(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId stopping ....");
}
public function onWorkerError(swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
{
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
}
public function onReceive(swoole_server $swooleServer, $fd, $fromId, $data)
{
echo "close $fd\n";
// var_dump($swooleServer->shutdown());
// swoole_server 接受数据之后立马关闭连接
var_dump($swooleServer->close($fd));
// $swooleServer->send($fd, $data);
}
}

View File

@ -0,0 +1,142 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
if (pcntl_fork() === 0) {
suicide(1000);
exit();
}
if (pcntl_fork() === 0) {
suicide(1000);
exit();
}
if (pcntl_fork() === 0) {
suicide(1000);
$cli = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
/** @noinspection PhpVoidFunctionResultUsedInspection */
assert($cli->set([
"socket_buffer_size" => 1024,
]));
$cli->on("connect", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
assert($cli->isConnected() === true);
$cli->send(str_repeat("\0", 1024));
});
$cli->on("receive", function(swoole_client $cli, $data){
$recv_len = strlen($data);
debug_log("receive: len $recv_len");
$cli->send(str_repeat("\0", $recv_len));
});
$cli->on("error", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
debug_log("error");
});
$cli->on("close", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
debug_log("close");
});
$cli->connect(TCP_SERVER_HOST, TCP_SERVER_PORT);
$cli->timeo_id = swoole_timer_after(1000, function() use($cli) {
debug_log("connect timeout");
$cli->close();
assert($cli->isConnected() === false);
});
exit();
}
(new TcpServer())->start();
class TcpServer
{
/**
* @var \swoole_server
*/
public $swooleServer;
public function __construct()
{
$this->swooleServer = new \swoole_server(TCP_SERVER_HOST, TCP_SERVER_PORT, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$this->swooleServer->set([
"buffer_output_size" => 1024 * 1024 * 1024, // 输出限制
"max_connection" => 10240,
"pipe_buffer_size" => 1024 * 1024 * 1024,
'daemonize' => 0,
'worker_num' => 2,
'max_request' => 100000,
'reactor_num' => 1,
// 'package_max_length' => 1024 * 1024 * 2
]);
}
public function start()
{
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('receive', [$this, 'onReceive']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->start();
}
public function onConnect()
{
debug_log("connecting ......");
}
public function onClose()
{
debug_log("closing .....");
}
public function onStart(swoole_server $swooleServer)
{
debug_log("swoole_server starting .....");
}
public function onShutdown(swoole_server $swooleServer)
{
debug_log("swoole_server shutdown .....");
}
public function onWorkerStart(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId starting .....");
}
public function onWorkerStop(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId stopping ....");
}
public function onWorkerError(swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
{
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
}
public function onReceive(swoole_server $swooleServer, $fd, $fromId, $data)
{
$recv_len = strlen($data);
debug_log("receive: len $recv_len");
$swooleServer->send($fd, str_repeat("\0", $recv_len));
}
}

View File

@ -0,0 +1,145 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
if (pcntl_fork() === 0) {
suicide(3000);
$cli = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
/** @noinspection PhpVoidFunctionResultUsedInspection */
assert($cli->set([
"socket_buffer_size" => 1,
]));
$cli->on("connect", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
// TODO getSocket BUG
// assert(is_resource($cli->getSocket()));
/*
$cli->getSocket();
// Warning: swoole_client_async::getSocket(): unable to obtain socket family Error: Bad file descriptor[9].
$cli->getSocket();
*/
assert($cli->isConnected() === true);
$cli->send(str_repeat("\0", 1024));
// $cli->sendfile(__DIR__.'/test.txt');
});
$cli->on("receive", function(swoole_client $cli, $data){
$recv_len = strlen($data);
debug_log("receive: len $recv_len");
$cli->send(str_repeat("\0", 1024));
});
$cli->on("error", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
debug_log("error");
});
$cli->on("close", function(swoole_client $cli) {
swoole_timer_clear($cli->timeo_id);
debug_log("close");
});
$cli->connect(TCP_SERVER_HOST, TCP_SERVER_PORT);
$cli->timeo_id = swoole_timer_after(1000, function() use($cli) {
debug_log("connect timeout");
$cli->close();
assert($cli->isConnected() === false);
});
exit();
}
(new TcpServer())->start();
class TcpServer
{
/**
* @var \swoole_server
*/
public $swooleServer;
public function __construct()
{
$this->swooleServer = new \swoole_server(TCP_SERVER_HOST, TCP_SERVER_PORT, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$this->swooleServer->set([
"buffer_output_size" => 1024 * 1024 * 1024, // 输出限制
"max_connection" => 10240,
"pipe_buffer_size" => 1024 * 1024 * 1024,
// 'log_file' => __DIR__ . '/send_fast_recv_slow.log',
'daemonize' => 0,
'worker_num' => 2,
'max_request' => 100000,
'reactor_num' => 1,
// 'package_max_length' => 1024 * 1024 * 2
]);
}
public function start()
{
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('receive', [$this, 'onReceive']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->start();
}
public function onConnect()
{
debug_log("connecting ......");
}
public function onClose()
{
debug_log("closing .....");
}
public function onStart(swoole_server $swooleServer)
{
debug_log("swoole_server starting .....");
}
public function onShutdown(swoole_server $swooleServer)
{
debug_log("swoole_server shutdown .....");
}
public function onWorkerStart(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId starting .....");
}
public function onWorkerStop(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId stopping ....");
}
public function onWorkerError(swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
{
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
}
public function onReceive(swoole_server $swooleServer, $fd, $fromId, $data)
{
$recv_len = strlen($data);
debug_log("receive: len $recv_len");
$swooleServer->send($fd, str_repeat("\0", $recv_len));
}
}

View File

@ -0,0 +1,114 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
/*
if (pcntl_fork() === 0) {
require_once __DIR__ . "/../swoole_client_async/simple_client.php";
exit();
}*/
(new TcpServer())->start();
class TcpServer
{
/**
* @var \swoole_server
*/
public $swooleServer;
public function __construct()
{
$this->swooleServer = new \swoole_server(TCP_SERVER_HOST, TCP_SERVER_PORT, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$this->swooleServer->set([
// "buffer_output_size" => 1024 * 1024 * 1024, // 输出限制
"max_connection" => 10240,
"pipe_buffer_size" => 1024 * 1024 * 1024,
// 'enable_port_reuse' => true,
// 'user' => 'www-data',
// 'group' => 'www-data',
// 'log_file' => __DIR__ . '/simple_server.log',
'dispatch_mode' => 2,
'open_tcp_nodelay' => 1,
'open_cpu_affinity' => 1,
'daemonize' => 0,
'reactor_num' => 1,
'worker_num' => 1,
'max_request' => 100000,
// 'package_max_length' => 1024 * 1024 * 2
/*
'open_length_check' => 1,
'package_length_type' => 'N',
'package_length_offset' => 0,
'package_body_offset' => 0,
'open_nova_protocol' => 1,
*/
]);
}
public function start()
{
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('receive', [$this, 'onReceive']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->start();
}
public function onConnect()
{
debug_log("connecting ......");
}
public function onClose()
{
debug_log("closing .....");
}
public function onStart(swoole_server $swooleServer)
{
debug_log("swoole_server starting .....");
}
public function onShutdown(swoole_server $swooleServer)
{
debug_log("swoole_server shutdown .....");
}
public function onWorkerStart(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId starting .....");
}
public function onWorkerStop(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId stopping ....");
}
public function onWorkerError(swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
{
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
}
public function onReceive(swoole_server $swooleServer, $fd, $fromId, $data)
{
if (trim($data) == 'shutdown')
{
$swooleServer->shutdown();
return;
}
$recv_len = strlen($data);
debug_log("receive: len $recv_len");
$swooleServer->send($fd, RandStr::gen($recv_len, RandStr::ALL));
// $swooleServer->close($fd);
}
}

View File

@ -0,0 +1,103 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//(new TcpServer($argv[1], $argv[2]))->start();
$host = isset($argv[1]) ? $argv[1] : TCP_SERVER_HOST;
$port = isset($argv[2]) ? $argv[2] : TCP_SERVER_PORT;
$server = new TcpServer($host, $port);
$server->start();
class TcpServer
{
/**
* @var \swoole_server
*/
public $swooleServer;
public function __construct($host, $port)
{
echo "swoole_server host:$host, port:$port\n";
$this->swooleServer = new \swoole_server($host, $port, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$this->swooleServer->set([
"pipe_buffer_size" => 1024 * 1024 * 1024,
'dispatch_mode' => 3,
'open_tcp_nodelay' => 1,
'open_cpu_affinity' => 1,
//'daemonize' => 1,
'reactor_num' => 2,
'worker_num' => 4,
'max_request' => 100000,
]);
}
public function start()
{
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('receive', [$this, 'onReceive']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->start();
}
public function onConnect()
{
debug_log("connecting ......");
}
public function onClose()
{
debug_log("closing .....");
}
public function onStart(swoole_server $swooleServer)
{
debug_log("swoole_server starting .....");
}
public function onShutdown(swoole_server $swooleServer)
{
debug_log("swoole_server shutdown .....");
}
public function onWorkerStart(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId starting .....");
if ($workerId == 0) {
swoole_timer_after(5000, function () {
$this->swooleServer->shutdown();
});
}
}
public function onWorkerStop(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId stopping ....");
}
public function onWorkerError(swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
{
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
}
public function onReceive(swoole_server $swooleServer, $fd, $fromId, $data)
{
//echo "swoole_server receive data: $data\n";
$recv_len = strlen($data);
debug_log("receive: len $recv_len");
//$swooleServer->send($fd, RandStr::gen($recv_len, RandStr::ALL));
$filename = __DIR__ . "/testsendfile.txt";
$swooleServer->sendfile($fd, $filename);
}
}

View File

@ -0,0 +1,89 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
(new UdpServer())->start();
class UdpServer
{
public $swooleServer;
public function __construct()
{
$this->swooleServer = new \swoole_server(UDP_SERVER_HOST, UDP_SERVER_PORT, SWOOLE_PROCESS, SWOOLE_SOCK_UDP);
$this->swooleServer->set([
"max_connection" => 1000,
'dispatch_mode' => 3,
'daemonize' => 0,
'reactor_num' => 4,
'worker_num' => 8,
'max_request' => 1000,
]);
}
public function start()
{
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('Packet', [$this, 'onPacket']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->start();
}
public function onConnect()
{
debug_log("connecting ......");
}
public function onClose()
{
debug_log("closing .....");
}
public function onStart(swoole_server $swooleServer)
{
debug_log("swoole_server starting .....");
}
public function onShutdown(swoole_server $swooleServer)
{
debug_log("swoole_server shutdown .....");
}
public function onWorkerStart(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId starting .....");
swoole_timer_after(3000, function() {
$this->swooleServer->shutdown();
});
}
public function onWorkerStop(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId stopping ....");
}
public function onWorkerError(swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
{
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
}
//UDP: 收到数据帧事件
public function onPacket(swoole_server $swooleServer, $data, $clientInfo)
{
if (trim($data) == 'shutdown')
{
$swooleServer->shutdown();
return;
}
//echo "clientInfo: $clientInfo, receive: $data\n";
$swooleServer->sendto($clientInfo['address'], $clientInfo['port'], $data);
}
}

View File

@ -0,0 +1,111 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
$host = isset($argv[1]) ? $argv[1] : TCP_SERVER_HOST;
$port = isset($argv[2]) ? $argv[2] : TCP_SERVER_PORT;
$server = new TcpServer($host, $port);
$server->start();
class TcpServer
{
public $swooleServer;
public function __construct($host, $port)
{
echo "swoole_server host:$host, port:$port\n";
$this->swooleServer = new \swoole_server($host, $port, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
$this->swooleServer->set([
"pipe_buffer_size" => 1024 * 1024 * 1024,
'dispatch_mode' => 3,
'open_tcp_nodelay' => 1,
'open_cpu_affinity' => 1,
//'daemonize' => 1,
'reactor_num' => 2,
'worker_num' => 4,
'task_worker_num' => 8,
'max_request' => 100000,
'log_file' => '/tmp/swoole_server.log',
]);
}
public function start()
{
$this->swooleServer->on('start', [$this, 'onStart']);
$this->swooleServer->on('shutdown', [$this, 'onShutdown']);
$this->swooleServer->on('workerStart', [$this, 'onWorkerStart']);
$this->swooleServer->on('workerStop', [$this, 'onWorkerStop']);
$this->swooleServer->on('workerError', [$this, 'onWorkerError']);
$this->swooleServer->on('connect', [$this, 'onConnect']);
$this->swooleServer->on('receive', [$this, 'onReceive']);
$this->swooleServer->on('task', [$this, 'onTask']);
$this->swooleServer->on('finish', [$this, 'onFinish']);
$this->swooleServer->on('close', [$this, 'onClose']);
$this->swooleServer->start();
}
public function onConnect()
{
debug_log("connecting ......");
}
public function onClose()
{
debug_log("closing .....");
}
public function onStart(swoole_server $swooleServer)
{
debug_log("swoole_server starting .....");
}
public function onShutdown(swoole_server $swooleServer)
{
debug_log("swoole_server shutdown .....");
}
public function onWorkerStart(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId starting .....");
if ($workerId == 0) {
//swoole_timer_after(5000, function () {
// $this->swooleServer->shutdown();
//});
}
}
public function onWorkerStop(swoole_server $swooleServer, $workerId)
{
debug_log("worker #$workerId stopping ....");
}
public function onWorkerError(swoole_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
{
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
}
public function onReceive(swoole_server $swooleServer, $fd, $fromId, $data)
{
//echo "swoole_server receive data: $data\n";
$param = array(
'fd' => $fd,
'data' => $data,
);
$swooleServer->task(json_encode($param));
//echo "send data to task worker.\n";
}
public function onTask(swoole_server $swooleServer, $task_id, $fromId, $data)
{
$task_data = json_decode($data, true);
$swooleServer->finish($task_data);
}
public function onFinish(swoole_server $swooleServer, $worker_task_id, $task_data)
{
$swooleServer->send($task_data['fd'], "OK");
}
}

View File

@ -0,0 +1 @@
testsendfile.txt

View File

@ -0,0 +1,21 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//swoole_function swoole_timer_after($ms, $callback, $param = null) {}
//swoole_function swoole_timer_tick($ms, $callback) {}
//swoole_function swoole_timer_clear($timer_id) {}
function after()
{
$start = microtime(true);
swoole_timer_after(1000, function() use($start) {
echo microtime(true) - $start, "\n";
after();
});
}
//for ($i = 0; $i < 10000; $i++) {
after();
//}

View File

@ -0,0 +1,79 @@
<?php
function fixRate(callable $callable, $interval)
{
return swoole_timer_tick($interval, $callable);
}
function fixDelay(callable $callable, $interval)
{
return swoole_timer_after($interval, function() use($callable, $interval) {
call_user_func($callable);
fixDelay($callable, $interval);
});
}
function randBlock()
{
$n = mt_rand(0, 10);
for ($i = 0; $i < 1000000 * $n; $i++) {}
}
/*
$t = microtime(true);
fixDelay(swoole_function() use(&$t) {
echo number_format(microtime(true) - $t, 3), PHP_EOL;
randBlock();
$t = microtime(true);
}, 1000);
//*/
/*
1.007
1.005
1.005
1.004
1.003
1.004
1.002
1.006
1.006
1.005
1.004
1.002
1.006
1.004
1.002
*/
/*
$t = microtime(true);
fixRate(swoole_function() use(&$t) {
echo number_format(microtime(true) - $t, 3), PHP_EOL;
randBlock();
$t = microtime(true);
}, 1000);
*/
/*
1.003
0.759
1.005
0.538
1.002
1.003
0.763
1.005
0.247
1.004
1.004
0.270
1.005
0.199
1.000
0.335
1.005
1.006
0.239
1.004
0.119
*/

View File

@ -0,0 +1,26 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
//swoole_function swoole_timer_after($ms, $callback, $param = null) {}
//swoole_function swoole_timer_tick($ms, $callback) {}
//swoole_function swoole_timer_clear($timer_id) {}
swoole_timer_after(-1, function(){ });
swoole_timer_tick(-1, function() { });
swoole_timer_after(86400001, function(){ });
swoole_timer_tick(86400001, function() { });
swoole_timer_clear(-1);
for ($i = 0; $i < 1000; $i++) {
swoole_timer_clear(swoole_timer_after(1, function() {}));
}
//swoole_timer_after(1, null);
//swoole_timer_after(1, "strlen");
function sw_timer_pass_ref(&$ref_func) {
swoole_timer_after(1, $ref_func);
}
$func = function() {};
sw_timer_pass_ref($func);

View File

@ -0,0 +1,9 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
for ($j = 0; $j < 100; $j++) {
swoole_timer_after(1, function() use($j){
echo $j, "\n";
});
}

View File

@ -0,0 +1,86 @@
<?php
// first shutdown func
// timer after
function func1()
{
register_shutdown_function(function() {
echo "first shutdown func\n";
});
// $start = microtime(true);
swoole_timer_after(1, function() /*use($start)*/ {
echo "timer after\n";
// echo (microtime(true) - $start) * 1000 - 1;
});
}
// first shutdown func
// timer after
function func1_2()
{
$order4 = function() { echo "first shutdown func\n"; };
$order5 = function() { swoole_event_wait(); };
$order6 = function() { echo "timer after\n";};
// order 1
register_shutdown_function($order4);
// order 2
register_shutdown_function($order5);
// order 3
swoole_timer_after(1, $order6);
}
// timer after
// first shutdown func
function func2()
{
register_shutdown_function(function() {
echo "first shutdown func\n";
});
swoole_timer_after(1, function() {
echo "timer after\n";
});
swoole_event_wait();
}
// first shutdown func
// timer after
// second shutdown func
function func3()
{
register_shutdown_function(function() {
echo "first shutdown func\n";
});
swoole_timer_after(1, function() {
echo "timer after\n";
register_shutdown_function(function() {
echo "second shutdown func\n";
});
});
}
function recv_shutdow()
{
register_shutdown_function(function() {
echo "shutdown\n";
recv_shutdow();
});
}
//recv_shutdow();
//func1();
func1_2();
//func2();
//func3();

View File

@ -0,0 +1,15 @@
<?php
//swoole_function swoole_get_local_ip() {}
//swoole_function swoole_strerror($errno) {}
//swoole_function swoole_errno() {}
require_once __DIR__ . "/../../../include/bootstrap.php";
$ip_list = swoole_get_local_ip();
print_r($ip_list);
echo swoole_errno(), "\n";
echo swoole_strerror(swoole_errno());

View File

@ -0,0 +1,27 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
require "websocket_client.php";
function send_large_request_data($host, $port)
{
$client = new WebSocketClient($host, $port);
if (!$client->connect())
{
echo "send failed, errCode={$client->errCode}\n";
return false;
}
$data = str_repeat("data", 40000);
for ($i = 0; $i < 100; $i++)
{
if (!$client->send($data))
{
echo "send failed, errCode={$client->errCode}\n";
return false;
}
$response = $client->recv();
assert($response == "SUCCESS", "response failed");
}
return true;
}

View File

@ -0,0 +1,18 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
require "websocket_client.php";
function send_small_request_data($host, $port)
{
$client = new WebSocketClient($host, $port);
$client->connect();
$data = "";
for ($i = 0; $i < 100; $i++)
{
$client->send($data);
$response = $client->recv();
assert($response == "SUCCESS", "response failed");
}
}

View File

@ -0,0 +1,118 @@
<?php
require_once __DIR__ . "/../../../include/bootstrap.php";
class WebSocketServer
{
/**
* @var \swoole_websocket_server
*/
public $webSocketServ;
public function __construct($host = WEBSOCKET_SERVER_HOST, $port = WEBSOCKET_SERVER_PORT)
{
$this->webSocketServ = new \swoole_websocket_server($host, $port);
$this->webSocketServ->set([
// 输出限制
"buffer_output_size" => 1024 * 1024 * 1024,
"max_connection" => 10240,
"pipe_buffer_size" => 1024 * 1024 * 1024,
// 'enable_port_reuse' => true,
'user' => 'www-data',
'group' => 'www-data',
// 'log_file' => __DIR__.'/swoole.log',
'open_tcp_nodelay' => 1,
'open_cpu_affinity' => 1,
'daemonize' => 0,
'reactor_num' => 1,
'worker_num' => 2,
'max_request' => 100000,
]);
}
public function start()
{
$this->webSocketServ->on('start', [$this, 'onStart']);
$this->webSocketServ->on('shutdown', [$this, 'onShutdown']);
$this->webSocketServ->on('workerStart', [$this, 'onWorkerStart']);
$this->webSocketServ->on('workerStop', [$this, 'onWorkerStop']);
$this->webSocketServ->on('workerError', [$this, 'onWorkerError']);
$this->webSocketServ->on('connect', [$this, 'onConnect']);
$this->webSocketServ->on('request', [$this, 'onRequest']);
$this->webSocketServ->on('open', [$this, 'onOpen']);
$this->webSocketServ->on('message', [$this, 'onMessage']);
$this->webSocketServ->on('close', [$this, 'onClose']);
$sock = $this->webSocketServ->getSocket();
if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) {
echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
}
$this->webSocketServ->start();
}
public function onConnect()
{
debug_log("connecting ......");
}
public function onClose()
{
debug_log("closing .....");
}
public function onStart(\swoole_websocket_server $swooleServer)
{
debug_log("swoole_server starting .....");
}
public function onShutdown(\swoole_websocket_server $swooleServer)
{
debug_log("swoole_server shutdown .....");
}
public function onWorkerStart(\swoole_websocket_server $swooleServer, $workerId)
{
debug_log("worker #$workerId starting .....");
}
public function onWorkerStop(\swoole_websocket_server $swooleServer, $workerId)
{
debug_log("worker #$workerId stopping ....");
}
public function onWorkerError(\swoole_websocket_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
{
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
}
public function onRequest(\swoole_http_request $request, \swoole_http_response $response)
{
$response->end("Hello World!");
}
public function onOpen(swoole_websocket_server $server, $request)
{
debug_log("{$request->fd} opened");
}
public function onMessage(swoole_websocket_server $server, $frame)
{
$server->push($frame->fd, "SUCCESS");
}
}
$host = isset($argv[1]) ? $argv[1] : WEBSOCKET_SERVER_HOST;
$port = isset($argv[2]) ? $argv[2] : WEBSOCKET_SERVER_PORT;
$wsServer = new WebSocketServer($host, $port);
$wsServer->start();

View File

@ -0,0 +1,391 @@
<?php
class WebSocketClient
{
const VERSION = '0.1.4';
const TOKEN_LENGHT = 16;
const TYPE_ID_WELCOME = 0;
const TYPE_ID_PREFIX = 1;
const TYPE_ID_CALL = 2;
const TYPE_ID_CALLRESULT = 3;
const TYPE_ID_ERROR = 4;
const TYPE_ID_SUBSCRIBE = 5;
const TYPE_ID_UNSUBSCRIBE = 6;
const TYPE_ID_PUBLISH = 7;
const TYPE_ID_EVENT = 8;
private $key;
private $host;
private $port;
private $path;
/**
* @var swoole_client
*/
private $socket;
private $buffer = '';
private $origin = null;
/**
* @var bool
*/
private $connected = false;
/**
* @param string $host
* @param int $port
* @param string $path
*/
function __construct($host = '127.0.0.1', $port = 8080, $path = '/', $origin = null)
{
$this->host = $host;
$this->port = $port;
$this->path = $path;
$this->origin = $origin;
$this->key = $this->generateToken(self::TOKEN_LENGHT);
}
/**
* Disconnect on destruct
*/
function __destruct()
{
$this->disconnect();
}
/**
* Connect client to swoole_server
*
* @return $this
*/
public function connect()
{
$this->socket = new \swoole_client(SWOOLE_SOCK_TCP);
if (!$this->socket->connect($this->host, $this->port))
{
return false;
}
$this->socket->send($this->createHeader());
return $this->recv();
}
public function getSocket()
{
return $this->socket;
}
/**
* Disconnect from swoole_server
*/
public function disconnect()
{
$this->connected = false;
$this->socket->close();
}
public function recv()
{
$data = $this->socket->recv();
if ($data === false)
{
echo "Error: {$this->socket->errMsg}";
return false;
}
$this->buffer .= $data;
$recv_data = $this->parseData($this->buffer);
if ($recv_data)
{
$this->buffer = '';
return $recv_data;
}
else
{
return false;
}
}
/**
* @param $data
* @param string $type
* @param bool $masked
*/
public function send($data, $type = 'text', $masked = true)
{
return $this->socket->send($this->hybi10Encode($data, $type, $masked));
}
/**
* Parse received data
*
* @param $response
*/
private function parseData($response)
{
if (!$this->connected && isset($response['Sec-Websocket-Accept']))
{
if (base64_encode(pack('H*', sha1($this->key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')))
=== $response['Sec-Websocket-Accept']
)
{
$this->connected = true;
}
else
{
throw new \Exception("error response key.");
}
}
return $this->hybi10Decode($response);
}
/**
* Create header for websocket client
*
* @return string
*/
private function createHeader()
{
$host = $this->host;
if ($host === '127.0.0.1' || $host === '0.0.0.0')
{
$host = 'localhost';
}
return "GET {$this->path} HTTP/1.1" . "\r\n" .
"Origin: {$this->origin}" . "\r\n" .
"Host: {$host}:{$this->port}" . "\r\n" .
"Sec-WebSocket-Key: {$this->key}" . "\r\n" .
"User-Agent: PHPWebSocketClient/" . self::VERSION . "\r\n" .
"Upgrade: websocket" . "\r\n" .
"Connection: Upgrade" . "\r\n" .
"Sec-WebSocket-Protocol: wamp" . "\r\n" .
"Sec-WebSocket-Version: 13" . "\r\n" . "\r\n";
}
/**
* Parse raw incoming data
*
* @param $header
*
* @return array
*/
private function parseIncomingRaw($header)
{
$retval = array();
$content = "";
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $header));
foreach ($fields as $field)
{
if (preg_match('/([^:]+): (.+)/m', $field, $match))
{
$match[1] = preg_replace_callback('/(?<=^|[\x09\x20\x2D])./',
function ($matches)
{
return strtoupper($matches[0]);
},
strtolower(trim($match[1])));
if (isset($retval[$match[1]]))
{
$retval[$match[1]] = array($retval[$match[1]], $match[2]);
}
else
{
$retval[$match[1]] = trim($match[2]);
}
}
else
{
if (preg_match('!HTTP/1\.\d (\d)* .!', $field))
{
$retval["status"] = $field;
}
else
{
$content .= $field . "\r\n";
}
}
}
$retval['content'] = $content;
return $retval;
}
/**
* Generate token
*
* @param int $length
*
* @return string
*/
private function generateToken($length)
{
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"§$%&/()=[]{}';
$useChars = array();
// select some random chars:
for ($i = 0; $i < $length; $i++)
{
$useChars[] = $characters[mt_rand(0, strlen($characters) - 1)];
}
// Add numbers
array_push($useChars, rand(0, 9), rand(0, 9), rand(0, 9));
shuffle($useChars);
$randomString = trim(implode('', $useChars));
$randomString = substr($randomString, 0, self::TOKEN_LENGHT);
return base64_encode($randomString);
}
/**
* Generate token
*
* @param int $length
*
* @return string
*/
public function generateAlphaNumToken($length)
{
$characters = str_split('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
srand((float)microtime() * 1000000);
$token = '';
do
{
shuffle($characters);
$token .= $characters[mt_rand(0, (count($characters) - 1))];
} while (strlen($token) < $length);
return $token;
}
/**
* @param $payload
* @param string $type
* @param bool $masked
*
* @return bool|string
*/
private function hybi10Encode($payload, $type = 'text', $masked = true)
{
$frameHead = array();
$frame = '';
$payloadLength = strlen($payload);
switch ($type)
{
case 'text':
// first byte indicates FIN, Text-Frame (10000001):
$frameHead[0] = 129;
break;
case 'close':
// first byte indicates FIN, Close Frame(10001000):
$frameHead[0] = 136;
break;
case 'ping':
// first byte indicates FIN, Ping frame (10001001):
$frameHead[0] = 137;
break;
case 'pong':
// first byte indicates FIN, Pong frame (10001010):
$frameHead[0] = 138;
break;
}
// set mask and payload length (using 1, 3 or 9 bytes)
if ($payloadLength > 65535)
{
$payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);
$frameHead[1] = ($masked === true) ? 255 : 127;
for ($i = 0; $i < 8; $i++)
{
$frameHead[$i + 2] = bindec($payloadLengthBin[$i]);
}
// most significant bit MUST be 0 (close connection if frame too big)
if ($frameHead[2] > 127)
{
$this->close(1004);
return false;
}
}
elseif ($payloadLength > 125)
{
$payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);
$frameHead[1] = ($masked === true) ? 254 : 126;
$frameHead[2] = bindec($payloadLengthBin[0]);
$frameHead[3] = bindec($payloadLengthBin[1]);
}
else
{
$frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;
}
// convert frame-head to string:
foreach (array_keys($frameHead) as $i)
{
$frameHead[$i] = chr($frameHead[$i]);
}
if ($masked === true)
{
// generate a random mask:
$mask = array();
for ($i = 0; $i < 4; $i++)
{
$mask[$i] = chr(rand(0, 255));
}
$frameHead = array_merge($frameHead, $mask);
}
$frame = implode('', $frameHead);
// append payload to frame:
for ($i = 0; $i < $payloadLength; $i++)
{
$frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
}
return $frame;
}
/**
* @param $data
*
* @return null|string
*/
private function hybi10Decode($data)
{
if (empty($data))
{
return null;
}
$bytes = $data;
$dataLength = '';
$mask = '';
$coded_data = '';
$decodedData = '';
$secondByte = sprintf('%08b', ord($bytes[1]));
$masked = ($secondByte[0] == '1') ? true : false;
$dataLength = ($masked === true) ? ord($bytes[1]) & 127 : ord($bytes[1]);
if ($masked === true)
{
if ($dataLength === 126)
{
$mask = substr($bytes, 4, 4);
$coded_data = substr($bytes, 8);
}
elseif ($dataLength === 127)
{
$mask = substr($bytes, 10, 4);
$coded_data = substr($bytes, 14);
}
else
{
$mask = substr($bytes, 2, 4);
$coded_data = substr($bytes, 6);
}
for ($i = 0; $i < strlen($coded_data); $i++)
{
$decodedData .= $coded_data[$i] ^ $mask[$i % 4];
}
}
else
{
if ($dataLength === 126)
{
$decodedData = substr($bytes, 4);
}
elseif ($dataLength === 127)
{
$decodedData = substr($bytes, 10);
}
else
{
$decodedData = substr($bytes, 2);
}
}
return $decodedData;
}
}

View File

@ -0,0 +1,30 @@
<?php
$serv = new \swoole_server('127.0.0.1', 9501, SWOOLE_BASE, SWOOLE_SOCK_TCP);
$serv->set([
// 'log_file' => __DIR__ . '/simple_server.log',
'dispatch_mode' => 2,
'daemonize' => 0,
'worker_num' => 1,
]);
$serv->on('workerStart', function (\swoole_server $serv)
{
/**
* @var $pm ProcessManager
*/
global $pm;
$pm->wakeup();
});
$serv->on('receive', function (swoole_server $serv, $fd, $rid, $data)
{
if (trim($data) == 'shutdown')
{
$serv->shutdown();
return;
}
$recv_len = strlen($data);
$serv->send($fd, RandStr::gen($recv_len, RandStr::ALL));
});
$serv->start();