codete php websocket what it is and when should you consider using it main fdb5671ed6
Codete Blog

PHP WebSocket – Everything You Need To Know

Patryk Grudniewski av 569835c2f8

20/10/2021 |

7 min read

Patryk Grudniewski

PHP WebSocket is a communication protocol standardized by the IETF as RFC 6455. It allows low-latency, fast, and efficient full-duplex communication between server and client. By taking advantage of it, both server and client applications can send data to each other at any time. It also means that the server is able to send data to the client without being requested first or even “request” some data from the client when needed (mind that the client would need to handle such a “request”).

But here, it’s just where the story begins, and there is much more to say about PHP Web Sockets. In this article, we’ll shed light on more and less known use cases of PHP WebSocket, its historical background, as well as its advantages over other technologies.

 

Table of contents:

1. PHP WebSocket in short. When it’s the best choice?

2. Creating a PHP WebSocket server – a few simple steps

3. PHP WebSockets implementations boiled down

PHP WebSocket in short. When it’s the best choice?

What’s in store, then, concerning Websocket PHP? Well, first of all, it’s good to emphasize that this full-duplex communications protocol was born out of the true and vital need for enhancing the process of interaction between the client and the server side. Its main goal was simply to make two-way real-time data transfer more effective. 

And that’s what it actually does, offering lower overhead than HTTP polling. With a little help of PHP WebSocket, sending and receiving messages in a real-time mode – the lifeblood of modern applications and devices – gets facilitated and triggered easily. And that is why PHP WebSocket outshines half-duplex solutions like HTTP polling.

 

Websocket PHP – historical background

In the past, creating web applications that needed two-way communication between the server and client was rather problematic. It simply required sending plenty of HTTP requests to check if the server had any updates. It was causing many problems of various nature, including the instances when:

  • the server was required to handle redundant requests even if no updates were available
  • excessive data was sent as every request-response pair had to transfer its own HTTP headers
  • client application had to track incoming responses as they could be provided in a different order than requests they’re corresponding to

All these issues could have been easily solved with the bidirectional connection that stays open as long as it is needed. And that is exactly what WebSocket provides today.

 

Is WebSocket just a better version of HTTP?

Somebody could ask, then, why do we need HTTP at all if the same task can be performed by WebSocket, and the latter offers even more. But it’s not that simple. When sending an HTTP request we can expect to get some kind of a response (or error) back and the same can’t be said about WebSocket. In fact, both server and client can send data whenever it is convenient for them. The only thing that the message sender can verify is if the message has been received by the receiver at all.

Basically, every time we need to receive a response (i.e. when getting some resources or saving data), it’s more secure (and much easier) to use the old-school HTTP connection. But whenever we want to enjoy a bidirectional, event-driven communication between client and server, WebSocket is the best option.

Creating a PHP WebSocket server – a few simple steps

PHP itself doesn’t provide a ready-to-use solution for WebSocket. Of course, we might create such from scratch using stream or socket functions. This would require, however, a profound understanding of the whole wire format for the data transfer part of WebSocket, as well as implementing it from the very beginning. Instead of that, we’re going to use the cboden/ratchet library from Packagist to set up the server.

A quick look at the Readme of the Ratchet and we are ready to create our first server:

class ChatServer implements Ratchet\MessageComponentInterface {
    private $clients;

    public function __construct() {
        $this->clients = new SplObjectStorage();
    }

    public function onOpen(Ratchet\ConnectionInterface $conn): void {
        $this->clients->attach($conn);
    }

    public function onMessage(Ratchet\ConnectionInterface $from, $message): void {
        foreach ($this->clients as $client) {
            if ($from !== $client) {
                $client->send($message);
            }
        }
    }

    public function onClose(Ratchet\ConnectionInterface $conn): void {
        $this->clients->detach($conn);
    }

    public function onError(Ratchet\ConnectionInterface $conn, Exception $e): void {
        $conn->close();
    }
}

$app = new Ratchet\App();
$app->route('/chat', new ChatServer(), ['*']);
$app->run();

Now it is only about running PHP script from the console.

As per the PHP WebSocket example above, we will send the message received to every connected client except the sender, the same as usual public chat does. Unfortunately, it becomes much more complicated when we want to send some data to the client independently from incoming data.

Let’s consider a situation when we have to send information to every WebSocket client on database state change. For simplification purposes, we will assume database changes are made only by REST API calls over HTTP and never via WebSocket protocol. In such case, it will not be difficult to identify changes made to the database (i.e. when using doctrine/orm, we could listen for postPersist, postUpdate, and postRemove events triggered by Doctrine’s Entity Manager), but there is no easy way to pass this information to our server as it is run as a separate PHP process.

The communication between the processes can be conducted in a few ways, including by:

  • creating a TCP socket between processes where a WebSocket server is a TCP socket server and an HTTP request processor is a client
  • setting up a certain queue system where an HTTP request processor would publish messages and a WebSocket server would consume them
  • connecting an HTTP request processor to WebSocket server via WebSocket protocol

It is clear that the last solution would be the easiest one as it doesn’t require modifications of Ratchet\App class to listen for something more than just WebSocket. What’s also worth emphasizing, is that the WebSocket route for receiving internal events needs to be secured so it is not accessible from the outside of your app.

PHP WebSockets implementations boiled down

Creating a WebSocket server in PHP from scratch can be a difficult task, indeed. Fortunately, we’ve got a bunch of libraries available via Packagist that can do this for us. With their help, setting up a very simple server is a matter of hours. But we need to keep in mind that it’s just the beginning of the WebSocket-related journey. As the PHP language is not designed for concurrency or listening for connections on multiple protocols, we will face multiple challenges when trying to tame WebSocket.

Another thing we have to remember is that most libraries available at Packagist are designed to live from request to response so they would need to be adjusted somehow for concurrent programming. In the above mentioned example, the ORM Doctrine that caches every read and every written entity in memory (and clears them when the script is over) would need to be modified so that it clears the cache eventually.

But I believe the reward of being able to send data to client applications any time we want exceeds the effort needed to achieve it. PHP WebSocket is simply very useful these days, as the demand for real-time, bi-directional applications and devices grows rapidly. And some of the notable advantages of WebSockets PHP include being lightweight for servers, compatible within various platforms, and faster than HTTP as well as long polling substitution.

And what are your experiences with PHP WebSocket? Do you find it useful and reliable enough for a web developer to give it a try? What kind of projects would you recommend it for? And can you spot any significant drawbacks of utilizing it?

Rated: 5.0 / 1 opinions
Patryk Grudniewski av 569835c2f8

Patryk Grudniewski

Software Developer at Codete. 8+ years of commercial experience, 20+ years of programming passion.

Our mission is to accelerate your growth through technology

Contact us

Codete Global
Spółka z ograniczoną odpowiedzialnością

Na Zjeździe 11
30-527 Kraków

NIP (VAT-ID): PL6762460401
REGON: 122745429
KRS: 0000983688

Get in Touch
  • icon facebook
  • icon linkedin
  • icon instagram
  • icon youtube
Offices
  • Kraków

    Na Zjeździe 11
    30-527 Kraków
    Poland

  • Lublin

    Wojciechowska 7E
    20-704 Lublin
    Poland

  • Berlin

    Bouchéstraße 12
    12435 Berlin
    Germany