# 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