简体   繁体   English

通过 php 中的多个 http 调用保持套接字连接

[英]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.我目前正在处理这个项目(php),我必须使用 sockets 将我的 php 后端连接到远程服务器。 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.我通过 HTTP 调用触发此代码,我试图避免创建多个 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.这是我到目前为止尝试的方法,但没有成功。

  • I tried using global variables $GLOBALS = array('globalsocket' => null);我尝试使用全局变量$GLOBALS = array('globalsocket' => null); but the variable is re-created every time a new request is triggered.但是每次触发新请求时都会重新创建变量。
  • I created a file where I tried to serialize the socket and unserialize it, but it did not work;我创建了一个文件,在其中尝试序列化套接字并反序列化它,但它不起作用; the unserialize socket was of no use反序列化套接字没有用
  • I tried class variable, but it was recreated each time of course我尝试了 class 变量,但每次都重新创建它
  • I read the documentation but almost all the methods need the instance of the socket in the first place, which is what I am trying to retrieve...我阅读了文档,但几乎所有方法首先都需要套接字的实例,这就是我想要检索的......
  • I also had a look at apc but it's not enabled on the server (and I cannot change that)我还查看了 apc 但它未在服务器上启用(我无法更改)

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 PS :我必须注意我习惯了nodejs而不是php,这可能是我很难弄清楚的原因

PPS : I don't have any database where I can store it PPS :我没有任何可以存储它的数据库

Here is how I would do what I want i nodejs这是我在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");

PHP is not a long-running process like Node. PHP 不像 Node.js 那样长时间运行的进程。 Given only the portion of code you provided, the PHP process would start up, open socket, write, and quit.仅给出您提供的部分代码,PHP 进程将启动、打开套接字、写入和退出。 This process would of course be repeated whenever you make a request to that PHP script.每当您向该 PHP 脚本发出请求时,当然会重复此过程。

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).要制作充当服务器的长时间运行的 PHP 脚本,您需要 1)需要从 CLI 运行它(这是您绕过最大执行时间的唯一方法,默认情况下为 30 秒),以及 2)您需要一个 while 循环或类似的循环来无限期地保持打开状态(或直到满足某些条件)。

Perhaps you'd be more comfortable with a PHP library for this purpose.也许您会更喜欢为此目的使用 PHP 库。

Some things to consider:需要考虑的一些事项:

http://socketo.me/ - PHP websocket server http://socketo.me/ - PHP websocket服务器

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

Background背景

PHP is works just like HTTP, basically stateless will initiate execution every-time it gets new request. PHP 的工作方式与 HTTP 类似,基本上无状态每次收到新请求时都会启动执行。 We sometime might need to run background jobs and process for which we need to utillize crontab or similar scheduler.我们有时可能需要运行需要使用 crontab 或类似调度程序的后台作业和进程。

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.注意:PHP 进程正在阻止 IO,因此您可以在服务器上使用 cli 并保持其运行来满足您的所有请求,但这将重新发明轮子。

Working approach工作方法

I'd suggest use: http://socketo.me/docs/hello-world我建议使用: 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.您可以继续使用这 4 个 function 来实现一切。 However you might need your custom logic to prevent your session or auth data.但是,您可能需要自定义逻辑来阻止您的 session 或身份验证数据。

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.并且您可以使用任何自定义脚本来检查它并在中断时保持运行,就像您使用 pm2 或 supervisor for node 一样。

Try and update us if this works for you.如果这对您有用,请尝试更新我们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM