werkint / reactphp-socket-client
Requires
- php: >=5.3.0
- react/dns: 0.4.*|0.3.*
- react/event-loop: 0.4.*|0.3.*
- react/promise: ^2.1 || ^1.2
- react/promise-timer: ~1.0
- react/stream: ^0.4.5
Requires (Dev)
- clue/block-react: ^1.1
README
基于 TCP/IP 和 SSL/TLS 的异步连接器。
简介
将此库视为 fsockopen()
或 stream_socket_client()
的异步版本。
在实际向远程服务器发送和接收数据之前,您必须与远程端建立连接。通过互联网/网络建立此连接需要一些时间,因为它需要完成几个步骤
- 通过 DNS (+缓存) 解析远程目标主机名
- 与远程目标 IP:端口的 TCP 握手(2 个往返)
- 可选:在新的连接上启用 SSL/TLS
用法
为了使用此项目,您需要以下 React boilerplate 代码来初始化主循环。
$loop = React\EventLoop\Factory::create();
ConnectorInterface
ConnectorInterface
负责提供建立流式连接的接口,例如普通的 TCP/IP 连接。
这是本包中定义的主要接口,并在 React 的庞大生态系统中使用。
大多数高级组件(如 HTTP、数据库或其他网络服务客户端)接受实现此接口的实例以创建其与底层网络服务的 TCP/IP 连接。这通常是通过依赖注入完成的,因此实际上交换此实现与其他接口的实现非常简单。
该接口仅提供一种方法
create()
create(string $host, int $port): PromiseInterface<Stream, Exception>
方法可用于建立流式连接。它返回一个 Promise,该 Promise 要么满足一个 Stream,要么拒绝一个 Exception
$connector->create('google.com', 443)->then( function (Stream $stream) { // connection successfully established }, function (Exception $error) { // failed to connect due to $error } );
返回的 Promise 应该被实现为可以在它仍然挂起时取消。取消挂起的 Promise 应该使用一个 Exception
拒绝其值。它应该根据适用性清理任何底层资源。
$promise = $connector->create($host, $port); $promise->cancel();
异步 TCP/IP 连接
React\SocketClient\TcpConnector
类实现了 ConnectorInterface
,并允许您创建到任何 IP-端口号组合的纯文本 TCP/IP 连接
$tcpConnector = new React\SocketClient\TcpConnector($loop); $tcpConnector->create('127.0.0.1', 80)->then(function (React\Stream\Stream $stream) { $stream->write('...'); $stream->end(); }); $loop->run();
请参阅第一个示例。
可以通过取消挂起的 Promise 来取消挂起的连接尝试
$promise = $tcpConnector->create($host, $port); $promise->cancel();
在挂起的 Promise 上调用 cancel()
将关闭底层的套接字资源,从而取消挂起的 TCP/IP 连接,并拒绝结果 Promise。
您可以可选地像这样向构造函数传递额外的 套接字上下文选项
$tcpConnector = new React\SocketClient\TcpConnector($loop, array( 'bindto' => '192.168.0.1:0' ));
请注意,此类只允许您连接到IP端口组合。如果您想连接到主机名端口组合,请参阅以下章节。
DNS解析
DnsConnector
类实现了ConnectorInterface
接口,允许您创建到任何主机名端口组合的明文TCP/IP连接。
它是通过装饰一个给定的TcpConnector
实例来实现的,这样它首先通过DNS(如果适用)查找给定的域名,然后与解析后的目标IP地址建立底层的TCP/IP连接。
请确保按照以下方式设置您的DNS解析器和底层的TCP连接器
$dnsResolverFactory = new React\Dns\Resolver\Factory(); $dns = $dnsResolverFactory->createCached('8.8.8.8', $loop); $dnsConnector = new React\SocketClient\DnsConnector($tcpConnector, $dns); $dnsConnector->create('www.google.com', 80)->then(function (React\Stream\Stream $stream) { $stream->write('...'); $stream->end(); }); $loop->run();
请参阅第一个示例。
可以通过取消挂起的 Promise 来取消挂起的连接尝试
$promise = $dnsConnector->create($host, $port); $promise->cancel();
在挂起的承诺上调用cancel()
将取消底层的DNS查找和/或底层的TCP/IP连接,并拒绝生成的承诺。
为了向后兼容,可以使用传统的Connector
类。它非常类似于较新的DnsConnector
,但需要按照以下方式设置
$connector = new React\SocketClient\Connector($loop, $dns); $connector->create('www.google.com', 80)->then($callback);
异步SSL/TLS连接
SecureConnector
类实现了ConnectorInterface
接口,允许您创建到任何主机名端口组合的安全TLS(以前称为SSL)连接。
它是通过装饰一个给定的DnsConnector
实例来实现的,这样它首先创建一个明文TCP/IP连接,然后在此流上启用TLS加密。
$secureConnector = new React\SocketClient\SecureConnector($dnsConnector, $loop); $secureConnector->create('www.google.com', 443)->then(function (React\Stream\Stream $stream) { $stream->write("GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n"); ... }); $loop->run();
请参阅第二个示例。
可以通过取消挂起的 Promise 来取消挂起的连接尝试
$promise = $secureConnector->create($host, $port); $promise->cancel();
在挂起的承诺上调用cancel()
将取消底层的TCP/IP连接和/或SSL/TLS协商,并拒绝生成的承诺。
您可以可选地像这样向构造函数传递额外的SSL上下文选项
$secureConnector = new React\SocketClient\SecureConnector($dnsConnector, $loop, array( 'verify_peer' => false, 'verify_peer_name' => false ));
高级用法:内部,
SecureConnector
必须在底层的流资源上设置所需的上下文选项。因此,它应该在连接器堆栈中的某个位置与TcpConnector
一起使用,以便为每个流资源分配一个空的上下文资源。否则,可能会出现一些难以追踪的竞争条件,因为所有流资源都将使用单个、共享的默认上下文资源。
连接超时
TimeoutConnector
类实现了ConnectorInterface
接口,允许您向任何现有的连接器实例添加超时处理。
它是通过装饰任何给定的ConnectorInterface
实例并启动一个计时器来实现的,该计时器将自动拒绝和取消任何底层连接尝试,如果它花费了太长时间。
$timeoutConnector = new React\SocketClient\TimeoutConnector($connector, 3.0, $loop); $timeoutConnector->create('google.com', 80)->then(function (React\Stream\Stream $stream) { // connection succeeded within 3.0 seconds });
请参阅任何示例。
可以通过取消挂起的 Promise 来取消挂起的连接尝试
$promise = $timeoutConnector->create($host, $port); $promise->cancel();
在挂起的承诺上调用cancel()
将取消底层的连接尝试,取消计时器并拒绝生成的承诺。
Unix域套接字
UnixConnector
类实现了ConnectorInterface
接口,允许您连接到Unix域套接字(UDS)路径,如下所示
$connector = new React\SocketClient\UnixConnector($loop); $connector->create('/tmp/demo.sock')->then(function (React\Stream\Stream $stream) { $stream->write("HELLO\n"); }); $loop->run();
连接到Unix域套接字是一个原子操作,即它的承诺将立即解决(解决或拒绝)。因此,在结果承诺上调用 cancel()
没有作用。
安装
安装此库的推荐方法是通过Composer。 新手使用Composer?
这将安装最新支持的版本
$ composer require react/socket-client:^0.5.3
有关版本升级的更多详细信息,请参阅CHANGELOG。
测试
要运行测试套件,您需要PHPUnit。转到项目根目录并运行
$ phpunit
测试套件还包括一些可选的集成测试,这些测试在TCP/IP套接字服务器上运行,并在其前面有一个可选的TLS/SSL终止代理。底层的TCP/IP套接字服务器将自动启动,而TLS/SSL终止代理则需要像这样启动并启用
$ stunnel -f -p stunnel.pem -d 6001 -r 6000 &
$ TEST_SECURE=6001 TEST_PLAIN=6000 phpunit
有关如何设置TLS/SSL终止代理和所需的证书文件(stunnel.pem
)的详细信息,请参阅Travis配置。如果您不确定。