I\'m trying to create a simple client/server application and thus I am experimenting with sockets in PHP.
Now I have a simple client in C# which connects to the server we
The current top answer here is wrong, you don't need multiple threads to handle multiple clients. You can use non-blocking I/O and stream_select
/ socket_select
to process messages from clients that are actionable. I'd recommend using the stream_socket_*
functions over socket_*
.
While non-blocking I/O works quite fine, you can't make any function calls with involve blocking I/O, otherwise that blocking I/O blocks the complete process and all clients hang, not just one.
That means all I/O has to be non-blocking or guaranteed to be very fast (which isn't perfect, but might be acceptable). Because not only your sockets need to use stream_select
, but you need to select on all open streams, I'd recommend a library that offers to register read and write watchers that are executed once a stream becomes readable / writable.
There are multiple such frameworks available, the most common ones are ReactPHP and Amp. The underlying event loops are pretty similar, but Amp offers a few more features on that side.
The main difference between the two is the approach for APIs. While ReactPHP uses callbacks everywhere, Amp tries to avoid them by using coroutines and optimizing its APIs for such a usage.
Amp's "Getting Started" guide is basically exactly about this topic. You can read the full guide here. I'll include a working example below.
read()) {
yield $socket->write($chunk);
}
};
$server = Amp\Socket\listen($uri);
while ($socket = yield $server->accept()) {
asyncCall($clientHandler, $socket);
}
});
Loop::run()
runs the event loop and watches for timer events, signals and actionable streams, which can be registered with Loop::on*()
methods. A server socket is created using Amp\Socket\listen()
. Server::accept()
returns a Promise
which can be used to await new client connections. It executes a coroutine once a client is accepted that reads from the client and echo's the same data back to it. For more details, refer to Amp's documentation.