# swoole_client
swoole_client提供了tcp/udp socket的客户端的封装代码,使用时仅需 new swoole_client 即可。 swoole的socket client对比PHP提供的stream族函数有哪些好处:
* stream函数存在超时设置的陷阱和Bug,一旦没处理好会导致Server端长时间阻塞
* fread有8192长度限制,无法支持UDP的大包
* swoole_client支持waitall,在知道包长度的情况下可以一次取完,不必循环取。
* swoole_client支持UDP connect,解决了UDP串包问题
* swoole_client是纯C的代码,专门处理socket,stream函数非常复杂。swoole_client性能更好
除了普通的同步阻塞+select的使用方法外,swoole_client还支持异步非阻塞回调。
[TOC=2,3]
## 同步阻塞客户端
```php
$client = new swoole_client(SWOOLE_SOCK_TCP);
if (!$client->connect('127.0.0.1', 9501, -1))
{
exit("connect failed. Error: {$client->errCode}\n");
}
$client->send("hello world\n");
echo $client->recv();
$client->close();
```
swoole_client支持长连接形式的同步客户端,方便在php-fpm环境中使用
```php
$cli = new swoole_client(SWOOLE_TCP | SWOOLE_KEEP);
```
**SWOOLE_KEEP只允许用于同步客户端**
加入SWOOLE_KEEP标志后,创建的TCP连接在PHP请求结束或者调用$cli->close时并不会关闭。下一次执行connect调用时会复用上一次创建的连接。长连接保存的方式默认是以ServerHost:ServerPort为key的(连接相同的host:port将复用已经存在的连接)。可以在第3个参数内指定key。
```php
swoole_client->__construct(int $sock_type, int $is_sync = SWOOLE_SOCK_SYNC, string $key);
```
**php-fpm/apache环境下只能使用同步客户端**
## 异步非阻塞客户端
```php
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$client->on("connect", function(swoole_client $cli) {
$cli->send("GET / HTTP/1.1\r\n\r\n");
});
$client->on("receive", function(swoole_client $cli, $data){
echo "Receive: $data";
$cli->send(str_repeat('A', 100)."\n");
sleep(1);
});
$client->on("error", function(swoole_client $cli){
echo "error\n";
});
$client->on("close", function(swoole_client $cli){
echo "Connection close\n";
});
$client->connect('127.0.0.1', 9501);
```
异步客户端只能使用在cli命令行环境 异步的swoole client的使用场景对于新手同学来说可能比较陌生,因为异步客户端是不可以应用在apache或fpm中的,而且仅能用于cli环境
## 并行调用
~~~
int swoole_client_select(array &$read, array &$write, array &$error, float $timeout);
~~~
别名swoole_select,swoole_client_select接受4个参数。
* $read, $write, $error 分别是可读/可写/错误的文件描述符。这3个参数必须是数组变量的引用。数组的元素必须为swoole_client对象。 1.8.6或更高版本可以支持swoole_process对象
* $timeout参数是select的超时时间,单位为秒,接受浮点数。
返回值
* 调用成功后,会返回事件的数量,并修改$read/$write/$error数组。使用foreach遍历数组,然后执行$item->recv/$item->send来收发数据。或者调用$item->close()或unset($item)来关闭socket。
* swoole_client_select返回0表示在规定的时间内,没有任何IO可用,select调用已超时。
**此函数可以用于Apache/PHP-fpm环境**
### swoole_client用法
~~~
$clients = array();
for($i=0; $i< 20; $i++)
{
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); //同步阻塞
$ret = $client->connect('127.0.0.1', 9501, 0.5, 0);
if(!$ret)
{
echo "Connect Server fail.errCode=".$client->errCode;
}
else
{
$client->send("HELLO WORLD\n");
$clients[$client->sock] = $client;
}
}
while (!empty($clients))
{
$write = $error = array();
$read = array_values($clients);
$n = swoole_client_select($read, $write, $error, 0.6);
if ($n > 0)
{
foreach ($read as $index => $c)
{
echo "Recv #{$c->sock}: " . $c->recv() . "\n";
unset($clients[$c->sock]);
}
}
}
~~~
### swoole_process用法
~~~
<?php
$process = new swoole_process(function (swoole_process $worker)
{
echo "Worker: start. PID=" . $worker->pid . "\n";
sleep(2);
$worker->write("hello master\n");
$worker->exit(0);
}, false);
$pid = $process->start();
$r = array($process);
$write = $error = array();
$ret = swoole_select($r, $write, $error, 1.0);//swoole_select是swoole_client_select的别名
var_dump($ret);
var_dump($process->read());
~~~
## 配置选项
Swoole\Client和Swoole\Http\Client可以使用set方法设置一些选项,启用某些特性。
### 结束符检测
~~~
$client->set(array(
'open_eof_check' => true,
'package_eof' => "\r\n\r\n",
'package_max_length' => 1024 * 1024 * 2,
))
~~~
### 长度检测
~~~
$client->set(array(
'open_length_check' => 1,
'package_length_type' => 'N',
'package_length_offset' => 0, //第N个字节是包长度的值
'package_body_offset' => 4, //第几个字节开始计算长度
'package_max_length' => 2000000, //协议最大长度
));
~~~
### Socket缓存区尺寸
~~~
$client->set(array(
'socket_buffer_size' => 1024*1024*2, //2M缓存区
));
~~~
包括socket底层操作系统缓存区、应用层接收数据内存缓存区、应用层发送数据内存缓冲区
关闭Nagle合并算法
~~~
$client->set(array(
'open_tcp_nodelay' => true,
));
~~~
### SSL/TLS证书
~~~
$client->set(array(
'ssl_cert_file' => $your_ssl_cert_file_path,
'ssl_key_file' => $your_ssl_key_file_path,
));
~~~
swoole-1.7.21或更高版本可用
### 绑定IP和端口
机器有多个网卡的情况下,设置bind_address参数可以强制客户端Socket绑定某个网络地址。
设置bind_port可以使客户端Socket使用固定的端口连接到外网服务器
~~~
$client->set(array(
'bind_address' => '192.168.1.100',
'bind_port' => 36002,
));
~~~
swoole-1.8.5或更高版本可用
### Socks5代理设置
~~~
$client->set(array(
'socks5_host' => '192.168.1.100',
'socks5_port' => 1080,
'socks5_username' => 'username',
'socks5_password' => 'password',
));
~~~
socks5_username、socks5_password为可选参数
### Http代理设置
~~~
$client->set(array(
'http_proxy_host' => '192.168.1.100',
'http_proxy_port' => 1080,
));
~~~
使用说明
目前支持open_length_check和open_eof_check2种自动协议处理功能,参考swoole_server中的配置选项
启用了自动协议后,同步阻塞客户端recv方法将不接受长度参数,每次必然返回一个完整的数据包
启用了自动协议后,异步非阻塞客户端onReceive每次必然返回一个完整的数据包
- swoole简介
- swoole功能概述
- 序章
- 开发必读
- 1 环境搭建
- 1.1 环境搭建
- 1.2 搭建Echo服务器
- 2 初识Swoole
- 2.1 Worker进程
- 2.2 TaskWorker进程
- 2.3 Timer定时器
- 2.4 Process进程
- 2.5 Table内存表
- 2.6 多端口监听
- 2.7 sendfile文件支持
- 2.8 SSL支持
- 2.9 热重启
- 2.10 http_server
- 附录*server配置
- 附录*server函数
- 附录*server属性
- 附录*server回调函数
- 附录*server高级特性
- 心跳检测
- 3 Swoole协议
- 3.1 EOF协议
- 3.2 固定包头协议
- 3.3 Http协议
- 3.4 WebSocket协议
- 3.5 MTQQ协议
- 内置http_server
- 内置websocket_server
- Swoole\Redis\Server
- 4 Swoole异步IO
- 4.1 AsyncIO
- 异步文件系统IO
- swoole_async_readfile
- swoole_async_writefile
- swoole_async_read
- swoole_async_write
- 5 swoole异步客户端
- ws_client
- http_client
- mysql_client
- redis_client
- tcp_client
- http2_client
- 6 swoole协程
- Swoole\Coroutine\Http\Client
- Swoole\Coroutine\MySQL
- Swoole\Coroutine\Redis
- Coroutine\PostgreSQL
- Swoole\Coroutine\Client
- Swoole\Coroutine\Socket
- Swoole\Coroutine\Channel
- Coroutine
- Swoole\Coroutine::create
- Swoole\Coroutine::resume
- Swoole\Coroutine::suspend
- Swoole\Coroutine::sleep
- Coroutine::getaddrinfo
- Coroutine::gethostbyname
- swoole_async_dns_lookup_coro
- Swoole\Coroutine::getuid
- getDefer
- setDefer
- recv
- Coroutine::stats
- Coroutine::fread
- Coroutine::fget
- Coroutine::fwrite
- Coroutine::readFIle
- Coroutine::writeFIle
- Coroutine::exec
- 7 swoole_process
- process::construct
- process::start
- process::name
- process::signal
- process::setaffinity
- process::exit
- process::kill
- process::daemon
- process->exec
- process::wait
- process::alarm
- 8 swoole定时器
- swoole_timer_tick
- swoole_timer_after
- swoole_timer_clear
- 9 swoole_event
- swoole_event_add
- swoole_event_set
- swoole_event_del
- swoole_event_wait
- swoole_event_defer
- swoole_event_write
- swoole_event_exit
- swoole提供的function
- 常见问题
- 客户端链接失败原因
- 如何设置进程数
- 如何实现异步任务
- 如何选择swoole三种模式
- php中哪些函数是阻塞的
- 是否可以共用1个redis或mysql连接
- 如何在回调函数中访问外部的变量
- 为什么不要send完后立即close
- 不同的Server程序实例间如何通信
- MySQL的连接池、异步、断线重连
- 在php-fpm或apache中使用swoole
- 学习Swoole需要掌握哪些基础知识
- 在phpinfo中有在php-m中没有
- 同步阻塞与异步非阻塞选择
- CURL发送POST请求服务器端超时
- 附录
- 预定义常量
- 内核参数调优
- php四种回调写法
- 守护进程程序常用数据结构
- swoole生命周期
- swoole_server中内存管理机制
- 使用jemalloc优化swoole内存分配性能
- Reactor、Worker、Task的关系
- Manager进程
- Swoole的实现
- Reactor线程
- 安装扩展
- swoole-worker手册
- swoole相关开源项目
- 写在后面的话
- 版本更新记录
- 4.0