node.js - Socket.io 3 and PHP integration

one text

Solution:

I was having the same problem with all the libraries that exists on github, the problem is that they are abandoned or not updated to socket.io V3.

In socket.io documentation says:

TL;DR: due to several breaking changes, a v2 client will not be able to connect to a v3 server (and vice versa)

To solve this problem, you need to learn how socket.io client works, this is easy because is in the protocol documentation, in the sample-session section.

Socket.Io protocol documentation

To solve this, you will need to forget the fsockopen and fwrite functions, you need to use CURL directly doing the requests mentioned in the protocol documentation.

Request n°1
GET
url: /socket.io/?EIO=4&transport=polling&t=N8hyd7H
Open packet: Open the connection between php and socket.io server. The server will return a "session id" named "sid", you will be adding this to the url query for the subsecuent queries.

Request n°2
POST
url: /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=sessionIdFromRequest1
post body: '40'
Namespace connection request: You need to send in the body the number 40, as a string, this means that you want to connect to socket.io "message" type

Request n°3
GET
url: /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=sessionIdFromRequest1
Namespace connection approval : This will return if the connection is successful or if there is an error, here is when the socket.io server authorizes your connection if you need a token.

Request n°4
POST
url: /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=sessionIdFromRequest1
post body: 42[event,data]
For example 42["notifications","Hi, Im a notification"] and is equivalent to socket.emit(event,data) Emit message to server: Send your message to the socket.io server.

Here is a BASIC example using Symfony 5.2 and HttpClientInterface:

<?php

// install dependencies before: composer require symfony/http-client

use Symfony\Component\HttpClient\CurlHttpClient;

include('vendor/autoload.php');

$client = new CurlHttpClient();
sendToSocket($client);

function sendToSocket(HttpClientInterface $client)
{
    $first = $client->request('GET', 'http://localhost:3000/socket.io/?EIO=4&transport=polling&t=N8hyd6w');
    $res = ltrim($first->getContent(), '0');
    $res = json_decode($res, true);
    $sid = $res['sid'];

    $second = $client->request('POST', 'http://localhost:3000/socket.io/?EIO=4&transport=polling&sid='.$sid, [
            'body' => '40'
        ]);
    $third = $client->request('GET', 'http://localhost:3000/socket.io/?EIO=4&transport=polling&sid='.$sid);

    $fourth = $client->request('POST', 'http://localhost:3000/socket.io/?EIO=4&transport=polling&sid='.$sid, [
        'body' => '42["notifications","Hi, Im a notification"]'
    ]);

}

As you can see, is very easy, and you dont need the troubling "copy-pasted" libraries out there. I said "copy-pasted" because all use the same code to open de socket and send the information, but no one is compatible with socket.io V3.

Here is an image, proving that the given code works as January 4 2021 with php 7.4, symfony 5.2 and socket.io V3.

Socket.io v3 php

This is my test server in node

// Install dependencies before: npm i express socket.io

const app = require('express')();
const http = require('http').createServer(app);

const io = require('socket.io')(http, {
   cors: {
      origin: "*",
      methods: ["GET", "POST"]
   }
});

io.on('connection', function (socket) {

   console.log("New Connection with transport", socket.conn.transport.name);

   socket.on('notifications', function (data) {
      console.log(data);
   });
});

http.listen(3000, () => {
   console.log('Server started port 3000');
});

I need to say that this solution works excellent if you want to send "one direction" messages to your socket.io server, like a new notification or whatever that doesn't need a permanent connection, is just "one shot" and nothing else.

Happy coding and greetings from Mexico.

Here is another example: Socket.io v3 php

First column is Postman making a request to the php server, simulating a server side event, like a new question created. In the response are the dumps of the response body from the 4 requests that you need to make.

Second column is the socket.IO node server running on port 3000

And the last column is the chrome console, simulating a user connected to the socket.IO server via websocket looking for notifications in 'questions' event.

Source