三十九、Swoole 基础学习笔记 - Swoole 协程 HTTP/WebSocket 客户端
hi,我是温新,一名PHPer
文章基于 Swoole 5.0.1 版本编写。
学习目标:学习协程 HTTP/WebSocket 服务器
说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!
协程版 HTTP
客户端的底层用纯 C
编写,不依赖任何第三方扩展库,拥有超高的性能。
- 支持
Http-Chunk
、Keep-Alive
特性,支持form-data
格式; -
HTTP
协议版本为HTTP/1.1
; - 支持升级为
WebSocket
客户端; -
gzip
压缩格式支持需要依赖zlib
库; - 客户端仅实现核心的功能,实际项目建议使用 Saber。
演示案例
HTTP Server/Client
协程 http 服务端
<?php
// 39-swoole-coroutine-server.php
Swoole\Coroutine\run(function () {
$http = new Swoole\Coroutine\Http\Server('0.0.0.0', 9502, false);
$http->handle('/', function ($request, $response) {
$response->end("<h1>Index</h1>");
});
$http->handle('/test', function ($request, $response) {
$response->end("<h1>Test</h1>");
});
$http->handle('/stop', function ($request, $response) use ($http) {
$response->end("<h1>Stop</h1>");
$http->shutdown();
});
$http->start();
});
协程客户端
<?php
// 39-swoole-coroutine-http-server.php
Swoole\Coroutine\run(function () {
$client = new Swoole\Coroutine\Http\Client('127.0.0.1', 9502);
$client->setHeaders([
'Host' => 'localhost',
'User-Agent' => 'Chrome/49.0.2587.3',
'Accept' => 'text/html,application/xhtml+xml,application/xml',
'Accept-Encoding' => 'gzip',
]);
$client->set(['timeout' => 1]);
// 发送 GET 请求
$client->get('/');
// 获取请求数据
echo $client->body;
$client->close();
});
输出结果
$php 39-swoole-coroutine-http-client.php
<h1>Index</h1>
WebSocket 客户端
websocket 服务端
<?php
// 39-swoole-websocket-server.php
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9503);
$ws->on('Open', function ($ws, $request) {
$ws->push($request->fd, "hello, welcome\n");
});
$ws->on('Message', function ($ws, $frame) {
echo "Message: {$frame->data}\n";
$ws->push($frame->fd, "server: {$frame->data}");
});
$ws->on('Close', function ($ws, $fd) {
echo "client-{$fd} is closed\n";
});
$ws->start();
协程客户端
<?php
// 39-swoole-coroutine-websocket-client.php
Swoole\Coroutine\run(function () {
$client = new Swoole\Coroutine\Http\Client('127.0.0.1', 9503);
$ws = $client->upgrade('/');
if ($ws) {
while(true) {
$client->push('hello');
var_dump($client->recv());
Swoole\Coroutine::sleep(0.1);
}
}
});
协程客户端 API 学习
__construct
含义:构造函数。
语法&参数:
Swoole\Coroutine\Http\Client::__construct(string $host, int $port, bool $ssl = false);
# 参数
$host:目标服务器主机地址;
$port:目标服务器主机端口;
$ssl:是否启用 ssl
set
含义:设置客户端参数。
语法&参数
Swoole\Coroutine\Http\Client->set(array $options);
# 参数
此方法与 Swoole\Client->set 接收的参数完全一致,可以参考 Swoole\Client->set;
此外,该 set 还增加了一些设置用于控制 HTTP 和 WebSocket 客户端。
额外选项
- 超时时间(timeout);
- 长连接(keep_alive);
- websocket_maxk - 客户端启用或关闭掩码。
get
含义:发送 GET 请求。
语法&参数:
Swoole\Coroutine\Http\Client->get(string $path): void
# 参数
$path:设置 URL 路径【如 /index.html,注意这里不能传入 http://domain】
post
含义:发送 post 请求。
语法&参数:
Swoole\Coroutine\Http\Client->post(string $path, mixed $data): void
# 参数
$path:设置 URL 路径【如 /index.html,注意这里不能传入 http://domain】
$data:请求的包体数据
服务端代码修改
$http->handle('/test', function ($request, $response) {
print_r($request->post);
$response->end("<h1>Test</h1>");
});
客户端代码修改
Swoole\Coroutine\run(function () {
$client = new Swoole\Coroutine\Http\Client('127.0.0.1', 9502);
$client->post('/test', ['web_name'=>'自如初']);
echo $client->body;
$client->close();
});
upgrade
含义:升级为 WebSocket 连接。
语法&参数:
Swoole\Coroutine\Http\Client->upgrade(string $path): bool
# 参数
$path:设置 URL 路径【如 /,注意这里不能传入 http://domain】
注意:
1、某些情况下请求虽然是成功的,
upgrade
返回了true
,但服务器并未设置HTTP
状态码为101
,而是200
或403
,这说明服务器拒绝了握手请求;2、
WebSocket
握手成功后可以使用push
方法向服务器端推送消息,也可以调用recv
接收消息;3、
upgrade
会产生一次协程调度。
push
含义:向 WebSocket
服务器推送消息。
语法&参数:
Swoole\Coroutine\Http\Client->push(mixed $data, int $opcode = WEBSOCKET_OPCODE_TEXT, bool $finish = true): bool
# 参数
$data:要发送的数据内容【默认为 UTF-8 文本格式,如果为其他格式编码或二进制数据,请使用 WEBSOCKET_OPCODE_BINARY】
$opcode:操作类型
$finish:操作类型
rece
含义:接收消息。只为 WebSocket
使用,需要配合 upgrade()
使用。
语法&参数:
Swoole\Coroutine\Http\Client->recv(float $timeout = 0)
# 参数
$timeout:超时时间
download
含义:通过 HTTP 下载文件。
语法&参数:
Swoole\Coroutine\Http\Client->download(string $path, string $filename, int $offset = 0): bool
# 参数
$path:设置 URL 路径
$filename:指定下载内容写入的文件路径【会自动写入到 downloadFile 属性】
$offset:功能:指定写入文件的偏移量【此选项可用于支持断点续传,可配合 HTTP 头 Range:bytes=$offset 实现】
setCookies
含义:设置 Cookie。
语法:Swoole\Coroutine\Http\Client->setCookies(array $cookies): void
。
getCookie
含义:获取 HTTP 响应的 cookie 内容。
语法:Swoole\Coroutine\Http\Client->getCookies(): array|false
案例:
Swoole\Coroutine\run(function () {
$client = new Swoole\Coroutine\Http\Client('127.0.0.1', 9502);
$client->setCookies(['age'=>19]);
var_dump($client->getCookies());
$client->close();
});
getBody
含义:获取 HTTP
响应的包体内容。
语法:Swoole\Coroutine\Http\Client->getBody(): string|false
close
含义:关闭连接。
语法:Swoole\Coroutine\Http\Client->close(): bool
函数:request()
含义:发起一个指定请求方式的请求。
函数:get()
含义:发起一个 get 请求
函数:post()
含义:发起一个 post 请求
案例:
Swoole\Coroutine\run(function () {
$data1 = Swoole\Coroutine\Http\request('http://localhost:9502/test', 'get');
$data2 = Swoole\Coroutine\Http\get('http://localhost:9502/test');
$data3 = Swoole\Coroutine\Http\post('http://localhost:9502/test',[]);
});
我是温新,本篇文章结束。