-
Notifications
You must be signed in to change notification settings - Fork 0
Transport TCP
Stream-oriented, reliable, in-order delivery. The default and most-tested transport in the package, backed by ext-sockets.
- The protocol expects an ordered byte stream (HTTP-like, line-based, custom framing on top of length-prefixed records).
- You need confirmation that bytes either arrived or the peer closed.
- Encryption is not required at this layer. (Use Transport TLS for that.)
use InitPHP\Socket\Socket;
use InitPHP\Socket\Enum\{Transport, Domain};
$server = Socket::server(Transport::TCP, '127.0.0.1', 9000, Domain::V4);
$server->backlog(16); // optional, default 8
$server->listen();
$server->live(function ($srv, $conn) {
$payload = $conn->read(1024);
if ($payload !== null) {
$conn->write("echo: {$payload}");
}
});Direct construction is also supported if you do not want the factory:
use InitPHP\Socket\Server\TCP as TcpServer;
$server = (new TcpServer('127.0.0.1', 9000, Domain::V4))->backlog(16);| Method | Default | Effect |
|---|---|---|
backlog(int $n) |
8 |
OS listen backlog for pending connections waiting to be accepted. |
backlog() is chainable and validates that $n >= 1 (throws SocketInvalidArgumentException otherwise).
For TCP the per-iteration flow is:
- Build
[listenSocket, ...activeClients]and hand it tosocket_selectwith the supplied timeout. - For every readable resource:
-
Listening →
socket_accept, wrap inTcpChannel, set non-blocking, register. -
Existing client →
isAlive()viaMSG_PEEK | MSG_DONTWAIT. Dead → close + evict. Alive → invoke the callback.
-
Listening →
socket_select failures with SOCKET_EINTR are treated as benign (just retry on the next iteration). Other failures throw SocketException.
use InitPHP\Socket\Socket;
use InitPHP\Socket\Enum\{Transport, Domain};
$client = Socket::client(Transport::TCP, '127.0.0.1', 9000, Domain::V4);
$client->connect();
$client->write("PING\r\n");
echo $client->read(1024, PHP_NORMAL_READ); // line-oriented read
$client->disconnect();read(int $length = 1024, int $type = PHP_BINARY_READ) matches PHP's socket_read:
| Constant | Behaviour |
|---|---|
PHP_BINARY_READ (default) |
Read up to $length raw bytes. |
PHP_NORMAL_READ |
Read until \n or \r is observed; the delimiter is included in the returned string. |
Socket::server(Transport::TCP, '127.0.0.1', 9000, Domain::V4); // IPv4 (default)
Socket::server(Transport::TCP, '::1', 9000, Domain::V6); // IPv6
Socket::server(Transport::TCP, '/tmp/initphp.sock', 1, Domain::UNIX); // UDSFor Domain::UNIX, the constructor still demands port >= 1. The port is ignored by the kernel for UDS — pass any non-zero placeholder. A real-world UDS pattern is:
$server = Socket::server(Transport::TCP, '/var/run/myapp.sock', 1, Domain::UNIX);
$server->listen();
chmod('/var/run/myapp.sock', 0660);The Domain enum maps to AF_INET / AF_INET6 / AF_UNIX internally; see Enums.
TCP supports a half-close where the peer stops sending but still receives. The package treats any zero-byte MSG_PEEK as full close — there is no shutdown() exposed. If you need half-close semantics, call socket_shutdown on $conn->getSocket() yourself.
backlog() controls the kernel's pending-accept queue. Under burst load with a slow tick() cadence, raising the backlog buys you time. If clients see ECONNREFUSED under load, raise it.
If you install signal handlers, socket_select will return false with socket_last_error() === SOCKET_EINTR whenever a signal fires during the call. The package treats this as benign and continues — no work is lost.
| Error | Exception |
|---|---|
socket_create fails |
SocketException |
socket_bind fails (port in use, perms, …) |
SocketException |
socket_listen fails |
SocketListenException |
socket_accept errors (non-EINTR) |
SocketConnectionException |
socket_select errors (non-EINTR) |
SocketException |
socket_connect fails |
SocketConnectionException |
backlog($n < 1) |
SocketInvalidArgumentException |
connect() twice on same client |
SocketException |
listen() twice on same server |
SocketException |
tick() before listen()
|
SocketException |
Every one of these implements SocketExceptionInterface so a single catch can guard the whole transport.
- Server Lifecycle / Client Lifecycle — what the methods do across states.
-
Connection and Channel — what
$conn->read()actually calls. - Recipe Echo Server — a runnable end-to-end example.
-
Recipe Chat Server —
register()+broadcast()patterns.
initphp/socket · MIT · PHP 8.1+ · part of the InitPHP family · file issues at InitPHP/Socket/issues
Getting started
Transports
Concepts
Reference
Recipes
Operational