三十七、Swoole 基础学习笔记 - Swoole 协程 TCP/UDP 客户端

作者: 温新

分类: 【Swoole 系列】

阅读: 793

时间: 2023-03-13 12:27:45

hi,我是温新,一名PHPer

文章基于 Swoole 5.0.1 版本编写。

学习目标:学习协程 TCP/UDP 服务器

说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!

协程 TCP/UDP 客户端

Coroutine\Client 提供了 TCP、UDP、unixSocket 传输协议的 Sockt 客户端封装代码,使用时仅需 new Swoole\Coroutine\Client 即可。

实现原理

  • 1、Coroutine\Client 的所有涉及网络请求的方法,Swoole 都会进行协程调度,业务层无感知;
  • 2、使用方法同 Client 同步模式方法完全一致;
  • 3、connect 超时设置同时作用于 ConnectRecvSend 超时。

继承关系

  • 1、Coroutine\Client 与 Client 不是继承关系,但 Client 提供的方法均可在 Coroutine\Client 中使用。
  • 2、在 Coroutine\Client 中可以使用 set 方法设置配置选项,使用方法和与 Client->set 完全一致。

协议处理

协程客户端也支持长度和 EOF 协议处理,设置方法与 Swoole\Client 完全一致。

<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$client</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">new</span> <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">Swoole\Coroutine\Client</span>(<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">SWOOLE_SOCK_TCP</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$client</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">set</span>(<span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">array</span>(</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'open_length_check'</span>     <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">true</span>,</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'package_length_type'</span>   <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'N'</span>,</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'package_length_offset'</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">0</span>, <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">//第N个字节是包长度的值</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'package_body_offset'</span>   <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">4</span>, <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">//第几个字节开始计算长度</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'package_max_length'</span>    <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">2000000</span>, <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">//协议最大长度</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">));</span>

客户端案例

<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important"><?</span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">php</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 37-swoole-coroutine-client.php</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">Swoole\Coroutine\run</span>(<span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> () {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$client</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">new</span> <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">Swoole\Coroutine\Client</span>(<span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">SWOOLE_SOCK_TCP</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">if</span> (<span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">!</span><span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$client</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">connect</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'127.0.0.1'</span>, <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">9501</span>, <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">0.5</span>)) {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">echo</span> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"connect failed. Error: </span>{<span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$client</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">errCode</span>}<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">\n"</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$client</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">send</span>(<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"我是协程客户端\n"</span>);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">echo</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$client</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">recv</span>();</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$client</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">close</span>();</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">});</span>

客户端 API

connect

含义:连接到远程服务器。

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

isConnected

含义:返回 Client 的连接状态。

语法:

<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">Swoole\Coroutine\Client</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">isConnected</span>(): <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">bool</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important"># 返回值</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">返回</span> <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">false,表示当前未连接到服务器</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">返回</span> <span style="box-sizing: border-box;color: rgb(18, 170, 228) !important">true,表示当前已连接到服务器</span></span>

send

含义:发送数据。

语法:Swoole\Coroutine\Client->send(string $data): int|bool

参数:$data:为发送的数据,必须为字符串类型,支持二进制数据。

recv

含义:recv 方法用于从服务器端接收数据。

语法:Swoole\Coroutine\Client->recv(float $timeout = 0): string|bool

close

含义:关闭连接。

语法:Swoole\Coroutine\Client->close(): bool

peek

含义:窥视数据。

语法:Swoole\Coroutine\Client->peek(int $length = 65535): string

set

含义:设置客户端参数

语法:Swoole\Coroutine\Client->set(array $settings): bool

Swoole\Client 的差异:

协程客户端提供了更细粒度的超时控制。可以设置:

  • timeout:总超时,包括连接、发送、接收所有超时
  • connect_timeout:连接超时
  • read_timeout:接收超时
  • write_timeout:发送超时

我是温新,本篇文章结束。

请登录后再评论