协程TCP/UDP客户端
优质
小牛编辑
146浏览
2023-12-01
Coroutine\Client
提供了TCP
、UDP
、unixSocket传输协议的Socket客户端封装代码,使用时仅需new Swoole\Coroutine\Client
即可。
实现原理
继承关系
Coroutine\Client
与Client并不是继承关系,但Client
提供的方法均可在Coroutine\Client
中使用。请参考 Swoole\Client,在此不再赘述 。- 在
Coroutine\Client
中可以使用set
方法设置配置选项,使用方法和与Client->set
完全一致,对于使用有区别的函数,在set()
函数小节会单独说明
使用示例
Co\run(function(){ $client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); if (!$client->connect('127.0.0.1', 9501, 0.5)) { echo "connect failed. Error: {$client->errCode}\n"; } $client->send("hello world\n"); echo $client->recv(); $client->close(); });
协议处理
协程客户端也支持长度和
EOF
协议处理,设置方法与 Swoole\Client 完全一致。$client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); $client->set(array( 'open_length_check' => 1, 'package_length_type' => 'N', 'package_length_offset' => 0, //第N个字节是包长度的值 'package_body_offset' => 4, //第几个字节开始计算长度 'package_max_length' => 2000000, //协议最大长度 ));
connect()
连接到远程服务器。
Swoole\Coroutine\Client->connect(string $host, int $port, float $timeout = 0.5): bool
参数
string $host
- 功能:远程服务器的地址【底层会自动进行协程切换解析域名为IP地址】
- 默认值:无
- 其它值:无
int $port
- 功能:远程服务器端口
- 默认值:无
- 其它值:无
float $timeout
- 功能:网络IO的超时时间;包括
connect/send/recv
,超时发生时,连接会被自动close
, 参考客户端超时规则 - 值单位: 秒【支持浮点型,如
1.5
表示1s
+500ms
】 - 默认值:
0.5s
- 其它值:无
- 功能:网络IO的超时时间;包括
提示
如果连接失败,会返回
false
超时后返回,检查
$cli->errCode
为110
失败重试
!>
connect
连接失败后,不可直接进行重连。必须使用close
关闭已有socket
,然后再进行connect
重试。//连接失败 if ($cli->connect('127.0.0.1', 9501) == false) { //关闭已有socket $cli->close(); //重试 $cli->connect('127.0.0.1', 9501); }
示例
if ($cli->connect('127.0.0.1', 9501)) { $cli->send("data"); } else { echo "connect failed."; }
send()
发送数据。
Swoole\Coroutine\Client->send(string $data): bool
参数
string $data
- 功能:为发送的数据,必须为字符串类型,支持二进制数据
- 默认值:无
- 其它值:无
发送成功返回写入
Socket
缓存区的字节数,底层会尽可能地将所有数据发出。如果返回的字节数与传入的$data
长度不同,可能是Socket
已被对端关闭,再下一次调用send
或recv
时将返回对应的错误码。发送失败返回false,可以使用
$client->errCode
获取错误原因。
recv()
recv方法用于从服务器端接收数据。
Swoole\Coroutine\Client->recv(float $timeout = -1): string
参数
float $timeout
- 功能:设置超时时间
- 值单位: 秒【支持浮点型,如
1.5
表示1s
+500ms
】 - 默认值:
-1
- 其它值:无
返回值
- 设置了通信协议,
recv
会返回完整的数据,长度受限于package_max_length - 未设置通信协议,
recv
最大返回64K
数据 - 未设置通信协议返回原始的数据,需要
PHP
代码中自行实现网络协议的处理 recv
返回空字符串表示服务端主动关闭连接,需要close
recv
失败,返回false
,检测$client->errCode
获取错误原因
- 设置了通信协议,
超时设置
- 传入了
$timeout
,优先使用指定的timeout
参数, 参考客户端超时规则 - 未传入
$timeout
,但在connect
时指定了超时时间,自动以connect
超时时间作为recv
超时时间 - 未传入
$timeout
,未设置connect
超时,将设置为-1
表示永不超时 - 发生超时的错误码为
ETIMEDOUT
- 传入了
close()
关闭连接。
!> close
不存在阻塞,会立即返回。关闭操作没有协程切换。
Swoole\Coroutine\Client->close(): bool
peek()
窥视数据。
!> peek
方法直接操作socket
,因此不会引起协程调度。
Swoole\Coroutine\Client->peek(int $length = 65535): string
提示
peek
方法仅用于窥视内核socket
缓存区中的数据,不进行偏移。使用peek
之后,再调用recv
仍然可以读取到这部分数据peek
方法是非阻塞的,它会立即返回。当socket
缓存区中有数据时,会返回数据内容。缓存区为空时返回false
,并设置$client->errCode
- 连接已被关闭
peek
会返回空字符串
set()
设置客户端参数。
Swoole\Coroutine\Client->set(array $settings): string
配置参数
- 请参考 Swoole\Client 。
和Swoole\Client的差异
协程客户端提供了更细粒度的超时控制。可以设置:
timeout
:总超时,包括连接、发送、接收所有超时connect_timeout
:连接超时read_timeout
:接收超时write_timeout
:发送超时- 参考客户端超时规则
示例
Co\run(function(){
$client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
$client->set(array(
'timeout' => 0.5,
'connect_timeout' => 1.0,
'write_timeout' => 10.0,
'read_timeout' => 0.5,
));
if (!$client->connect('127.0.0.1', 9501, 0.5))
{
echo "connect failed. Error: {$client->errCode}\n";
}
$client->send("hello world\n");
echo $client->recv();
$client->close();
});