Bastien L.
Bastien L.

Reputation: 149

Persist socket connection over multiple http calls in php

I am currently working on this project (php) where I have to connect my php backend to a remote server using sockets. I am using this code to create the connection and it works fine:

$key=base64_encode(openssl_random_pseudo_bytes(16));
$head = "GET / HTTP/1.1"."\r\n".
      "Upgrade: WebSocket"."\r\n".
      "Pragma: no-cache"."\r\n".
      "Accept-Encoding: gzip, deflate"."\r\n".
      "Connection: Upgrade"."\r\n".
      "Origin: http://$host"."\r\n".
      "Host: $host"."\r\n".
      "Sec-WebSocket-Version: 13"."\r\n".
      "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits"."\r\n".
      "Sec-WebSocket-Protocol: b_xmlproc"."\r\n".
      "Cache-Control: no-cache"."\r\n".
      "Sec-WebSocket-Key: $key"."\r\n".
      "Content-Length: 0\r\n"."\r\n";
$sock = pfsockopen($host, $port, $errno, $errstr, 2);
fwrite($sock, $head ) or die('error:'.$errno.':'.$errstr);

I trigger this code through an HTTP call and I am trying to avoid creating multiple sockets. For the moment, every time I am triggering this endpoint, a new socket is created. However, I would like to use pre-existing socket if one has been created already instead of a new one. Here is what I tried so far, without success.

If anyone has a clue on how to do that, I would much appreciate ! Thanks.

PS: I must note that I am used to nodejs and not php, which may be the reason why I am having a hard time figuring it out

PPS: I don't have any database where I can store it

Here is how I would do what I want i nodejs


var net = require("net");
const http = require("http");

let client = new net.Socket();
let connected = false;
const requestListener = function (req, res) {
    console.log("status", client.listening);
    if (!connected) {
        client.connect("port", "ip", function () {
            console.log("Connected");
            connected = true;
            
        });
    }

    res.writeHead(200);
    res.end("Hello, World!");
};
const server = http.createServer(requestListener);

client.on("data", function (data) {
    console.log("Received: " + data);
    client.destroy(); // kill client after server's response
});

client.on("close", function () {
    connected = false;
    console.log("Connection closed");
});

client.on("end", function(){
    console.log("Connection end");
    connected = false;
    client.destroy()
})

client.on('error', function(){
    console.log("Connection end");
    connected = false;
    client.destroy()
})

server.listen("xxx");

Upvotes: 0

Views: 1297

Answers (2)

Dheeraj Thedijje
Dheeraj Thedijje

Reputation: 1059

Background

PHP is works just like HTTP, basically stateless will initiate execution every-time it gets new request. We sometime might need to run background jobs and process for which we need to utillize crontab or similar scheduler.

Note: PHP process is blocking IO so you can though use cli on server and keep it running to entertain all your request but that will be reinventing the wheel.

Working approach

I'd suggest use: http://socketo.me/docs/hello-world

From example on above link

<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Chat implements MessageComponentInterface {
    public function onOpen(ConnectionInterface $conn) {
    }

    public function onMessage(ConnectionInterface $from, $msg) {
    }

    public function onClose(ConnectionInterface $conn) {
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
    }
}

You can keep using these 4 function to achieve everything. However you might need your custom logic to prevent your session or auth data.

this also use a background process which you need to execute on server.

php bin/chat-server.php

and you can use any custom script to check and keep it running if interrupted, just like you use pm2 or supervisor for node.

Try and update us if this works for you.

Upvotes: 0

caffeinatedbits
caffeinatedbits

Reputation: 491

PHP is not a long-running process like Node. Given only the portion of code you provided, the PHP process would start up, open socket, write, and quit. This process would of course be repeated whenever you make a request to that PHP script.

To make a long running PHP script that acts as a server, you'd 1) need to run it from CLI (this is the only way you'll bypass max execution time, which is by default 30 seconds), and 2) you'd need a while loop or similar to keep it open indefinitely (or until some condition is met).

Perhaps you'd be more comfortable with a PHP library for this purpose.

Some things to consider:

http://socketo.me/ - PHP websocket server

https://github.com/ratchetphp/Pawl - PHP websocket client

Upvotes: 1

Related Questions