【问题标题】:Persist socket connection over multiple http calls in php在php中通过多个http调用保持套接字连接
【发布时间】:2021-03-13 15:58:51
【问题描述】:

我目前正在处理这个项目 (php),我必须使用套接字将我的 php 后端连接到远程服务器。我正在使用这段代码来创建连接,它工作正常:

$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);

我通过 HTTP 调用触发此代码,并试图避免创建多个套接字。目前,每次我触发这个端点时,都会创建一个新的套接字。但是,如果已经创建了一个而不是新的,我想使用预先存在的套接字。这是我到目前为止尝试的方法,但没有成功。

  • 我尝试使用全局变量$GLOBALS = array('globalsocket' => null);,但每次触发新请求时都会重新创建该变量。
  • 我创建了一个文件,我在其中尝试序列化套接字并取消序列化它,但它不起作用;反序列化套接字没有用
  • 我尝试了类变量,但当然每次都会重新创建它
  • 我阅读了文档,但几乎所有方法首先都需要套接字实例,这就是我要检索的内容...
  • 我还查看了 apc,但它未在服务器上启用(我无法更改)

如果有人知道如何做到这一点,我将不胜感激!谢谢。

PS:我必须注意我习惯了nodejs而不是php,这可能是我很难弄清楚的原因

PPS:我没有可以存储它的数据库

这就是我在 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");

【问题讨论】:

  • 虽然它没有在任何地方提到这一点,但我认为您可以使用相同的参数再次调用pfsockopen(),以重用持久连接。有一些警告。见:stackoverflow.com/questions/8099248/…
  • 感谢您的回答,但我不确定它是否有效。我尝试使用自定义套接字服务器(用 nodejs 编写),在其中记录每个新连接 wss.on( "connection", (connection = async (ws) => { console.log("new connection");}),并且我有两个用于两个 http 调用的日志:/
  • 那是完全用另一种语言进行的测试,我认为这不会告诉你任何关于 PHP 的信息。这是另一个链接,关于同一件事:stackoverflow.com/questions/14268018/…所有问题和答案都表明重复使用它只是意味着打开相同的连接。
  • 嗯,对不起;我的意思是我确实在nodejs中设置了一个“假”后端来测试当我的另一个php后端使用pfsockopen连接时它是否接收到两个不同的连接。由于我在触发连接时收到了两次消息“新连接”,这意味着 php back 必须第二次创建了一个新连接,并且与前一个不同(在这种情况下,连接上的侦听器不应该有第二次触发)
  • 谢谢@BastienL。我认为 Node 和 PHP 世界之间的最大区别在于 Node 既是服务器又是框架,而对于 PHP,服务器(特别是客户端与之交谈的)与 PHP 框架分离(Apache/Nginx),而当 PHP 是在 web 上下文中运行,服务器真的期待 PHP 最终“完成”。这也不是特定于套接字的。因此,您可能需要创建一个连续运行的服务器端 PHP 应用程序,然后再创建一个与之对话的 PHP 应用程序。您也可以尝试生成后台任务,但我不会长期信任它

标签: php sockets persistence


【解决方案1】:

PHP 不像 Node.js 那样需要长时间运行。仅给定您提供的部分代码,PHP 进程将启动、打开套接字、写入和退出。每当您向该 PHP 脚本发出请求时,当然会重复此过程。

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

也许您更愿意为此目的使用 PHP 库。

需要考虑的一些事项:

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

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

【讨论】:

    【解决方案2】:

    背景

    PHP 的工作方式与 HTTP 类似,基本上无状态会在每次收到新请求时启动执行。我们有时可能需要运行需要使用 crontab 或类似调度程序的后台作业和进程。

    注意: PHP 进程正在阻塞 IO,因此您可以在服务器上使用 cli 并保持其运行来满足您的所有请求,但这将是重新发明轮子。

    工作方法

    我建议使用:http://socketo.me/docs/hello-world

    以上链接示例

    <?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) {
        }
    }
    

    您可以继续使用这 4 个功能来实现一切。但是,您可能需要自定义逻辑来阻止会话或身份验证数据。

    这也使用您需要在服务器上执行的后台进程。

    php bin/chat-server.php
    

    并且您可以使用任何自定义脚本来检查并在中断时保持运行,就像您使用 pm2 或 supervisor for node。

    如果这对您有用,请尝试更新我们。

    【讨论】:

      猜你喜欢
      • 2015-04-25
      • 2016-12-04
      • 1970-01-01
      • 2010-12-01
      • 1970-01-01
      • 2015-09-23
      • 1970-01-01
      • 2011-04-28
      • 1970-01-01
      相关资源
      最近更新 更多