icicleio / socket
Asynchronous stream socket server and client for Icicle.
Installs: 48 188
Dependents: 5
Suggesters: 0
Security: 0
Stars: 16
Watchers: 5
Forks: 2
Open Issues: 4
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
This library is a component for Icicle, providing an asynchronous stream socket server, connector, and datagram. Like other Icicle components, this library uses Coroutines built from Awaitables and Generators to make writing asynchronous code more like writing synchronous code.
Requirements
- PHP 5.5+ for v0.5.x branch (current stable) and v1.x branch (mirrors current stable)
- PHP 7 for v2.0 branch (under development) supporting generator delegation and return expressions
Suggested
- openssl extension: Enables using SSL/TLS on sockets.
Installation
The recommended way to install is with the Composer package manager. (See the Composer installation guide for information on installing and using Composer.)
Run the following command to use this library in your project:
composer require icicleio/socket
You can also manually edit composer.json
to add this library as a project requirement.
// composer.json { "require": { "icicleio/socket": "^0.5" } }
The socket component implements network sockets as coroutine-based streams, server, and datagram. Creating a server and accepting connections is very simple, requiring only a few lines of code.
The example below implements a simple HTTP server listening on 127.0.0.1:8080 that responds to any request with the contents of the client request as the body of the response. This example is implemented using coroutines (see the Coroutine API documentation) and the basic sockets provided by this package.
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();
Documentation
- Server
- BasicServer Constructor - Creates a server from a stream socket server resource.
- accept() - A coroutine that is resolved when a client connects.
- getAddress() - Returns the address of the server.
- getPort() - Returns the port of the server.
- ServerFactory
- create() - Creates a
Server
on a given host and port.
- create() - Creates a
- Socket
- NetworkSocket Constructor - Creates a socket object from a stream socket resource.
- enableCrypto() - Enables crypto on the socket.
- isCryptoEnabled() - Determines if crypto is enabled on the socket.
- unshift() - Shifts data back to the front of the socket stream.
- getLocalAddress() - Returns the local address of the socket.
- getLocalPort() - Returns the local port of the socket.
- getRemoteAddress() - Returns the remote address of the socket.
- getRemotePort() - Returns the remote port of the socket.
- Connector
- connect() - A coroutine resolved with a
Socket
object when a connection is established.
- connect() - A coroutine resolved with a
- Datagram - UDP socket listener
- BasicDatagram Constructor
- receive() - Receives data from the datagram.
- send() - Sends data to a address and port.
- getAddress() - Returns the address of the datagram.
- getPort() - Returns the port of the datagram.
- DatagramFactory
- create() - Creates a
Datagram
on a given host and port.
- create() - Creates a
- Functions
- connect() - Uses the global connector to connect to the given IP and port.
- connector() - Accesses or sets the global connector instance.
Function prototypes
Prototypes for object instance methods are described below using the following syntax:
ClassOrInterfaceName::methodName(ArgumentType $arg): ReturnType
Server
The Icicle\Socket\Server\BasicServer
class implements Icicle\Socket\Server\Server
, a coroutine-based interface for creating a TCP server and accepting connections.
BasicServer Constructor
$server = new BasicServer(resource $socket)
Creates a server from a stream socket server resource generated from stream_socket_server()
. Generally it is better to use Icicle\Socket\Server\DefaultServerFactory
to create a Icicle\Socket\Server\BasicServer
instance.
accept()
Server::accept(): Generator
A coroutine that is resolved with an object implementing Icicle\Socket\Socket
when a connection is accepted.
getAddress()
Server::getAddress(): string
Returns the local IP address as a string.
getPort()
Server::getPort(): int
Returns the local port.
ServerFactory
Icicle\Socket\Server\DefaultServerFactory
(implements Icicle\Socket\Server\ServerFactory
) can be used to create server instances from a IP or unix socket path, port number (null
for unix socket), and list of options.
create()
ServerFactory::create( string $host, int $port = null, mixed[] $options = [] ): Server
Creates a server bound and listening on the given ip or unix socket path and port number (null
for unix socket).
Socket
Icicle\Socket\NetworkSocket
objects implement Icicle\Socket\Socket
and are used as the fulfillment value of the coroutine returned by Icicle\Socket\Server\BasicServer::accept()
(see documentation above). (Note that Icicle\Socket\Server\BasicServer
can be easily extended and modified to fulfill accept requests with different objects implementing Icicle\Socket\Socket
.)
The class extends Icicle\Stream\Pipe\DuplexPipe
, so it inherits all the readable and writable stream methods as well as adding those below.
NetworkSocket Constructor
$socket = new NetworkSocket(resource $socket)
Creates a socket object from the given stream socket resource.
enableCrypto()
Socket::enableCrypto(int $method, float $timeout = 0): \Generator
Enables encryption on the socket. For Socket objects created from Icicle\Socket\Server\Server::accept()
, a PEM file must have been provided when creating the server socket (see Icicle\Socket\Server\ServerFactory
). Use the STREAM_CRYPTO_METHOD_*_SERVER
constants when enabling crypto on remote clients (e.g., created by Icicle\Socket\Server\Server::accept()
) and the STREAM_CRYPTO_METHOD_*_CLIENT
constants when enabling crypto on a local client connection (e.g., created by Icicle\Socket\Connector\Connector::connect()
).
isCryptoEnabled()
Socket::isCryptoEnabled(): bool
Determines if encryption is enabled on the socket.
unshift()
Socket::unshift(string $data): void
Determines if encryption is enabled on the socket.
getLocalAddress()
Socket::getLocalAddress(): string
Returns the local IP address as a string.
getLocalPort()
Socket::getLocalPort(): int
Returns the local port.
getRemoteAddress()
Socket::getRemoteAddress(): string
Returns the remote IP address as a string.
getRemotePort()
Socket::getRemotePort(): int
Returns the remote port.
Connector
The Icicle\Socket\Connector\DefaultConnector
class (implements Icicle\Socket\Connector\Connector
) asynchronously connects to a remote server, returning a coroutine that is fulfilled with an instance of Icicle\Socket\Socket
when the connection is successfully established. Note that the host should be given as an IP address, as DNS lookups performed by PHP are synchronous (blocking). If you wish to use domain names instead of IPs, see Icicle\Dns\Connector\Connector
in the DNS component.
connect()
Connector::connect( string $host, int|null $port, mixed[] $options = [] ): \Generator
Connects asynchronously to the given IP or unix socket path on the given port number (null
for unix socket).
Datagram
The Icicle\Socket\Datagram\BasicDatagram
class implements Icicle\Socket\Datagram\Datagram
, a coroutine-based interface for creating a UDP listener and sender.
BasicDatagram Constructor
$datagram = new BasicDatagram(resource $socket)
Creates a datagram from a stream socket server resource generated from stream_socket_server()
. Generally it is better to use Icicle\Socket\Datagram\DefaultDatagramFactory
to create a Icicle\Socket\Datagram\BasicDatagram
instance.
receive()
Datagram::receive(int $length, float $timeout): Generator
A coroutine that is fulfilled with an array when a data is received on the UDP socket (datagram). The array is a 0-indexed array containing the IP address, port, and data received, in that order.
send()
Datagram::send( string $address, int $port, string $data ): \Generator
Send the given data to the IP address and port. This coroutine is fulfilled with the amount of data sent once the data has successfully been sent.
getAddress()
Datagram::getAddress(): string
Returns the local IP address as a string.
getPort()
Datagram::getPort(): int
Returns the local port.
DatagramFactory
Icicle\Socket\Datagram\DefaultDatagramFactory
(implements Icicle\Socket\Datagram\DatagramFactory
) can be used to create datagram instances from a hostname or unix socket path, port number (null
for unix socket), and list of options.
create()
DatagramFactory::create( string $host, int $port = null, mixed[] $options = [] ): Datagram
Creates a datagram bound and listening on the given IP and port number. No options are defined in this implementation.
Functions
Socket\connect()
Icicle\Socket\connect( string $ip, int|null $port, array $options = [] ): \Generator
Connects asynchronously to the given host on the given port. Uses the global connector interface that can be set using Icicle\Socket\connector()
.
Socket\connector()
Icicle\Socket\connector( Connector|null $connector = null ): Connector
Gets the global connector instance. If a Connector
instance is provided, that instance is set as the global connector instance.