Socket Programming with PHP
debt(d8/e7/b6/t6)
Closest to 'silent in production until users hit it' (d8, between d7 and d9). detection_hints.automated is no; socket bugs like partial reads or missing SO_REUSEADDR only surface under load or after restarts, slightly catchable via runtime testing.
Closest to 'cross-cutting refactor across the codebase' (e7). quick_fix suggests switching to ReactPHP/Swoole for production — that's an architectural shift in I/O model, not a one-line change, though staying within socket APIs and adding SO_REUSEADDR/partial-read handling is lighter.
Closest to 'strong gravitational pull' (b6, between b5 and b7). Socket server choice shapes the entire CLI/daemon process model; blocking vs async dictates how all connection handling code is written, but scope is limited to CLI context per applies_to.
Closest to 'serious trap' (b6, between t5 and t7). Per misconception, devs assume PHP sockets scale like Node/Go; common_mistakes shows TCP partial-read trap contradicts message-oriented assumptions most devs bring from higher-level APIs.
TL;DR
Explanation
Two socket APIs in PHP: (1) Sockets extension (socket_create, socket_bind, socket_listen, socket_accept) — low-level, POSIX-like. (2) Stream sockets (stream_socket_client, stream_socket_server) — higher level, supports SSL, uses fread/fwrite. For most cases, use Guzzle (HTTP), AMQP libraries (queues), or ReactPHP/Swoole for async sockets. Raw sockets are useful for: custom TCP/UDP protocols, network diagnostics, building WebSocket servers. Non-blocking sockets with socket_set_nonblock and socket_select() enable handling multiple connections. PHP's socket support is blocking by default — use ReactPHP or Swoole for production async networking.
Common Misconception
Why It Matters
Common Mistakes
- Using blocking sockets in production servers — limits to one connection at a time.
- Not setting SO_REUSEADDR — port in use errors after restart.
- Not handling partial reads — TCP streams can split messages across packets.
Code Examples
// Blocking TCP server — handles one connection at a time:
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8080);
socket_listen($socket);
$client = socket_accept($socket); // Blocks until connection
// Non-blocking with stream sockets:
$server = stream_socket_server('tcp://0.0.0.0:8080', $errno, $errstr);
stream_set_blocking($server, false);
while (true) {
$client = @stream_socket_accept($server, 0);
if ($client) {
$data = fread($client, 1024);
fwrite($client, "HTTP/1.1 200 OK\r\n\r\nHello");
fclose($client);
}
// In production: use ReactPHP or Swoole for proper async
}