icicleio / socket
为 Icicle 提供的异步流套接字服务器和客户端。
Requires
- icicleio/icicle: ^0.9.1
- icicleio/stream: ^0.5.4
Requires (Dev)
- phpunit/phpunit: ^4.6
Suggests
- ext-openssl: Enables using SSL/TLS on stream sockets.
README
这个库是 Icicle 的组件,提供异步流套接字服务器、连接器和数据报。与其他 Icicle 组件一样,这个库使用从 可等待 和 生成器 构建的自定义协程,使得编写异步代码更像编写同步代码。
要求
- PHP 5.5+ 用于 v0.5.x 分支(当前稳定版)和 v1.x 分支(镜像当前稳定版)
- PHP 7 用于 v2.0 分支(开发中)支持生成器委托和返回表达式
建议
- openssl 扩展:在套接字上启用 SSL/TLS。
安装
推荐使用 Composer 包管理器安装。有关安装和使用 Composer 的信息,请参阅 Composer 安装指南。
运行以下命令在项目中使用此库
composer require icicleio/socket
您也可以手动编辑 composer.json
将此库添加为项目依赖项。
// composer.json { "require": { "icicleio/socket": "^0.5" } }
套接字组件实现基于协程的网络套接字,包括服务器和数据报。创建服务器和接受连接非常简单,只需几行代码。
以下示例实现了一个简单的 HTTP 服务器,监听 127.0.0.1:8080,并以客户端请求的内容作为响应体。此示例使用协程(请参阅 协程 API 文档)和此包提供的基本套接字。
use Icicle\Coroutine\Coroutine; use Icicle\Loop; use Icicle\Socket\Server\DefaultServerFactory; use Icicle\Socket\Server\Server; use Icicle\Socket\Socket; $server = (new DefaultServerFactory())->create('localhost', 8080); $generator = function (Server $server) { printf("Server listening on %s:%d\n", $server->getAddress(), $server->getPort()); $generator = function (Socket $socket) { $request = ''; do { $request .= (yield $socket->read(0, "\n")); } while (substr($request, -4) !== "\r\n\r\n"); $message = sprintf("Received the following request:\r\n\r\n%s", $request); $data = "HTTP/1.1 200 OK\r\n"; $data .= "Content-Type: text/plain\r\n"; $data .= sprintf("Content-Length: %d\r\n", strlen($message)); $data .= "Connection: close\r\n"; $data .= "\r\n"; $data .= $message; yield $socket->write($data); $socket->close(); }; while ($server->isOpen()) { // Handle client in a separate coroutine so this coroutine is not blocked. $coroutine = new Coroutine($generator(yield $server->accept())); $coroutine->done(null, function ($exception) { printf("Client error: %s\n", $exception->getMessage()); }); } }; $coroutine = new Coroutine($generator($server)); $coroutine->done(); Loop\run();
文档
- 服务器
- BasicServer 构造函数 - 从流套接字服务器资源创建服务器。
- accept() - 当客户端连接时解决的协程。
- getAddress() - 返回服务器的地址。
- getPort() - 返回服务器的端口号。
- ServerFactory
- create() - 在指定的主机和端口上创建一个
Server
。
- create() - 在指定的主机和端口上创建一个
- 套接字
- NetworkSocket 构造函数 - 从流套接字资源创建套接字对象。
- enableCrypto() - 在套接字上启用加密。
- isCryptoEnabled() - 判断套接字上是否启用了加密。
- unshift() - 将数据移回到套接字流的开始位置。
- getLocalAddress() - 返回套接字的本地地址。
- getLocalPort() - 返回套接字的本地端口号。
- getRemoteAddress() - 返回套接字的远程地址。
- getRemotePort() - 返回套接字的远程端口。
- 连接器
- connect() - 当建立连接时,通过一个
Socket
对象解析的协程。
- connect() - 当建立连接时,通过一个
- Datagram - UDP 套接字监听器
- BasicDatagram 构造函数
- receive() - 从数据报接收数据。
- send() - 向地址和端口发送数据。
- getAddress() - 返回数据报的地址。
- getPort() - 返回数据报的端口。
- DatagramFactory
- create() - 在给定的主机和端口上创建一个
Datagram
。
- create() - 在给定的主机和端口上创建一个
- 函数
- connect() - 使用全局连接器连接到给定的 IP 和端口。
- connector() - 访问或设置全局连接器实例。
函数原型
以下语法描述了对象实例方法的原型
ClassOrInterfaceName::methodName(ArgumentType $arg): ReturnType
服务器
Icicle\Socket\Server\BasicServer
类实现了 Icicle\Socket\Server\Server
,这是一个用于创建 TCP 服务器和接受连接的基于协程的接口。
BasicServer 构造函数
$server = new BasicServer(resource $socket)
从一个由 stream_socket_server()
生成的流套接字服务器资源创建服务器。通常最好使用 Icicle\Socket\Server\DefaultServerFactory
来创建 Icicle\Socket\Server\BasicServer
实例。
accept()
Server::accept(): Generator
一个协程,当接受连接时,通过实现 Icicle\Socket\Socket
的对象解析。
getAddress()
Server::getAddress(): string
以字符串形式返回本地 IP 地址。
getPort()
Server::getPort(): int
返回本地端口。
ServerFactory
Icicle\Socket\Server\DefaultServerFactory
(实现 Icicle\Socket\Server\ServerFactory
)可用于从 IP 或 UNIX 套接字路径、端口号(UNIX 套接字为 null
)和选项列表创建服务器实例。
create()
ServerFactory::create( string $host, int $port = null, mixed[] $options = [] ): Server
创建一个绑定并监听给定 IP 或 UNIX 套接字路径和端口号(UNIX 套接字为 null
)的服务器。
套接字
Icicle\Socket\NetworkSocket
对象实现了 Icicle\Socket\Socket
,并用作由 Icicle\Socket\Server\BasicServer::accept()
返回的协程的完成值(请参阅上面的文档)。(注意,Icicle\Socket\Server\BasicServer
可以很容易地扩展和修改,以便使用实现 Icicle\Socket\Socket
的不同对象来满足接受请求。)
该类扩展了 Icicle\Stream\Pipe\DuplexPipe
,因此继承了所有可读和可写流方法,并添加了以下方法。
NetworkSocket 构造函数
$socket = new NetworkSocket(resource $socket)
从给定的流套接字资源创建套接字对象。
enableCrypto()
Socket::enableCrypto(int $method, float $timeout = 0): \Generator
在套接字上启用加密。对于从 Icicle\Socket\Server\Server::accept()
创建的套接字对象,在创建服务器套接字时必须已提供 PEM 文件(请参阅 Icicle\Socket\Server\ServerFactory
)。当在远程客户端(例如,由 Icicle\Socket\Server\Server::accept()
创建)上启用加密时,使用 STREAM_CRYPTO_METHOD_*_SERVER
常量,当在本地客户端连接(例如,由 Icicle\Socket\Connector\Connector::connect()
创建)上启用加密时,使用 STREAM_CRYPTO_METHOD_*_CLIENT
常量。
isCryptoEnabled()
Socket::isCryptoEnabled(): bool
确定是否在套接字上启用了加密。
unshift()
Socket::unshift(string $data): void
确定是否在套接字上启用了加密。
getLocalAddress()
Socket::getLocalAddress(): string
以字符串形式返回本地 IP 地址。
getLocalPort()
Socket::getLocalPort(): int
返回本地端口。
getRemoteAddress()
Socket::getRemoteAddress(): string
以字符串形式返回远程 IP 地址。
getRemotePort()
Socket::getRemotePort(): int
返回远程端口。
连接器
Icicle\Socket\Connector\DefaultConnector
类(实现了 Icicle\Socket\Connector\Connector
接口)异步连接到远程服务器,当连接成功建立时,返回一个协程,该协程被填充为 Icicle\Socket\Socket
实例。请注意,主机应以 IP 地址的形式给出,因为 PHP 执行的 DNS 查找是同步的(阻塞的)。如果您想使用域名而不是 IP 地址,请参阅 DNS 组件 中的 Icicle\Dns\Connector\Connector
。
connect()
Connector::connect( string $host, int|null $port, mixed[] $options = [] ): \Generator
异步连接到给定 IP 地址或 Unix 套接字路径上的指定端口号(对于 Unix 套接字为 null
)。
数据报
Icicle\Socket\Datagram\BasicDatagram
类实现了 Icicle\Socket\Datagram\Datagram
,这是一个基于协程的接口,用于创建 UDP 监听器和发送器。
BasicDatagram 构造函数
$datagram = new BasicDatagram(resource $socket)
从由 stream_socket_server()
生成的流套接字服务器资源创建数据报。通常,使用 Icicle\Socket\Datagram\DefaultDatagramFactory
创建 Icicle\Socket\Datagram\BasicDatagram
实例会更好。
receive()
Datagram::receive(int $length, float $timeout): Generator
当在 UDP 套接字(数据报)上接收到数据时,这是一个协程,其结果为数组。该数组是一个包含 IP 地址、端口和接收到的数据的 0 索引数组,顺序为 IP 地址、端口和数据。
send()
Datagram::send( string $address, int $port, string $data ): \Generator
将给定的数据发送到指定的 IP 地址和端口号。一旦数据成功发送,该协程就会填充发送的数据量。
getAddress()
Datagram::getAddress(): string
以字符串形式返回本地 IP 地址。
getPort()
Datagram::getPort(): int
返回本地端口。
DatagramFactory
Icicle\Socket\Datagram\DefaultDatagramFactory
(实现了 Icicle\Socket\Datagram\DatagramFactory
接口)可用于从主机名或 Unix 套接字路径、端口号(对于 Unix 套接字为 null
)和选项列表创建数据报实例。
create()
DatagramFactory::create( string $host, int $port = null, mixed[] $options = [] ): Datagram
创建一个绑定并监听给定 IP 地址和端口号的数据报。此实现中没有定义任何选项。
函数
Socket\connect()
Icicle\Socket\connect( string $ip, int|null $port, array $options = [] ): \Generator
异步连接到给定主机上的指定端口。使用全局连接器接口,该接口可以使用 Icicle\Socket\connector()
设置。
Socket\connector()
Icicle\Socket\connector( Connector|null $connector = null ): Connector
获取全局连接器实例。如果提供了 Connector
实例,则该实例被设置为全局连接器实例。