Swoole\Client

Swoole\Client 以下简称 Client,提供了 TCP/UDPsocket 的客户端的封装代码,使用时仅需 new Swoole\Client 即可。可用于 FPM/Apache 环境。
相对传统的 streams 系列函数,有几大优势:

  • stream 函数存在超时设置的陷阱和 Bug,一旦没处理好会导致 Server 端长时间阻塞
  • stream 函数的 fread 默认最大 8192 长度限制,无法支持 UDP 的大包
  • Client 支持 waitall,在有确定包长度时可一次取完,不必循环读取
  • Client 支持 UDP Connect,解决了 UDP 串包问题
  • Client 是纯 C 的代码,专门处理 socketstream 函数非常复杂。Client 性能更好
  • Client 支持长连接
  • 可以使用 swoole_client_select 函数实现多个 Client 的并发控制

    完整示例

    1. $client = new Swoole\Client(SWOOLE_SOCK_TCP);
    2. if (!$client->connect('127.0.0.1', 9501, -1)) {
    3. echo "connect failed. Error: {$client->errCode}\n";
    4. // 失败重连
    5. $client->close(true);
    6. $client->connect('127.0.0.1', 9501);
    7. }
    8. $client->send("hello world\n");
    9. echo $client->recv();
    10. $client->close();
    不支持 Apacheprework 多线程模式

    方法

    __construct()

    方法格式

    Swoole\Client->__construct(int $sock_type, int $is_sync = SWOOLE_SOCK_SYNC, string $key);

参数介绍

int $sock_type

  • 功能:表示 socket 的类型【支持 SWOOLE_SOCK_TCPSWOOLE_SOCK_TCP6SWOOLE_SOCK_UDPSWOOLE_SOCK_UDP6

    int $is_sync

  • 功能:同步阻塞模式,现在只有这一个类型,保留此参数只为了兼容 api

    string $key

  • 功能:用于长连接的 Key【默认使用 IP:PORT 作为 key。相同的 keynew 两次也只用一个 TCP 连接】, 达到复用的目的.

在 PHP-FPM/Apache 中创建长连接

$cli = new Swoole\Client(SWOOLE_SOCK_TCP | SWOOLE_KEEP);

加入 SWOOLE_KEEP 标志后,创建的 TCP 连接在 PHP 请求结束或者调用 $cli->close() 时并不会关闭。下一次执行 connect 调用时会复用上一次创建的连接。长连接保存的方式默认是以 ServerHost:ServerPortkey 的。可以在第 3 个参数内指定 key
Client 对象析构会自动调用 close 方法关闭 socket

connect()

方法格式

Swoole\Client->connect(string $host, int $port, float $timeout = 0.5, int $flag = 0): bool

参数介绍

string $host

  • 功能:服务器地址【支持自动异步解析域名,$host 可直接传入域名】

    int $port

  • 功能:服务器端口

    float $timeout

  • 功能:设置超时时间

  • 值单位: 秒【支持浮点型,如 1.5 表示 1s+500ms
  • 默认值0.5

    int $flag

  • UDP 类型时表示是否启用 udp_connect 设定此选项后将绑定 $host$port,此 UDP 将会丢弃非指定 host/port 的数据包。

  • TCP 类型,$flag=1 表示设置为非阻塞 socket,之后此 fd 会变成异步 IO,connect 会立即返回。如果将 $flag 设置为 1,那么在 send/recv 前必须使用 swoole_client_select 来检测是否完成了连接。

默认底层并不会启用 udp connect,一个 UDP 客户端执行 connect 时,底层在创建 socket 后会立即返回成功。这时此 socket 绑定的地址是 0.0.0.0,任何其他对端均可向此端口发送数据包。
$client->connect('192.168.1.100', 9502),这时操作系统为客户端 socket 随机分配了一个端口 58232,其他机器,如 192.168.1.101 也可以向这个端口发送数据包。
未开启 udp connect,调用 getsockname 返回的 host 项为 0.0.0.0
启用 udp connect$client->connect('192.168.1.100', 9502, 1, 1)。这时将会绑定客户端和服务器端,底层会根据服务器端的地址来绑定 socket 绑定的地址。如连接了 192.168.1.100,当前 socket 会被绑定到 192.168.1.* 的本机地址上。启用 udp connect 后,客户端将不再接收其他主机向此端口发送的数据包。

返回值

  • 成功返回 true
  • 失败返回 false,请检查 errCode 属性获取失败原因

    失败重连

    connect 失败后如果希望重连一次,必须先进行 close 关闭旧的 socket,否则会返回 EINPROCESS 错误,因为当前的 socket 正在连接服务器,客户端并不知道是否连接成功,所以无法再次执行 connect。调用 close 会关闭当前的 socket,底层重新创建新的 socket 来进行连接。
    1. if ($socket->connect('127.0.0.1', 9502) === false) {
    2. $socket->close(true);
    3. $socket->connect('127.0.0.1', 9502);
    4. }