Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/236.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php ZMQ订阅服务器在长时间间隔后未收到来自远程服务器的消息_Php_Sockets_Zeromq_Publish Subscribe_Pyzmq - Fatal编程技术网

Php ZMQ订阅服务器在长时间间隔后未收到来自远程服务器的消息

Php ZMQ订阅服务器在长时间间隔后未收到来自远程服务器的消息,php,sockets,zeromq,publish-subscribe,pyzmq,Php,Sockets,Zeromq,Publish Subscribe,Pyzmq,当两个php都在同一台服务器上运行时,以下pubsub php正常工作。但是,当它们在不同的服务器上运行时,它不起作用 (local)client.php <--> (local)server.php (with sleeptime 300) <= OK (local)client.php <--> (remote)server.php (with sleeptime 300) <= NG (local)client.php(local)server.php

当两个php都在同一台服务器上运行时,以下pubsub php正常工作。但是,当它们在不同的服务器上运行时,它不起作用

(local)client.php <--> (local)server.php (with sleeptime 300) <= OK
(local)client.php <--> (remote)server.php (with sleeptime 300) <= NG

(local)client.php(local)server.php(带sleeptime 300)我在php中使用ZeroMQ来发送对时间敏感的实时信号。首先,一些理论:互联网工程任务组(IETF)和指定TCP。在这种情况下,感兴趣的属性是用户超时。用户超时在中得到了最好的解释,这是一项建议,旨在实现应用程序之间通信用户超时设置的标准:

传输控制协议(TCP)规范[RFC0793]定义了一个本地、每连接“用户超时”参数,该参数 指定传输数据可能保留的最大时间量 在TCP之前未确认将强制关闭相应的 连接。应用程序可以使用OPEN设置和更改此参数 并发送电话。如果端到端连接中断持续时间更长 超过用户超时时,发送方将不会收到对的确认 任何传输尝试,包括保持生命,它将关闭 发生用户超时时的TCP连接

在没有应用程序指定的用户超时的情况下,TCP 规范[RFC0793]定义了5分钟的默认用户超时。 主机需求RFC[RFC1122]通过 引入两个阈值R1和R2(R2>R1),用于控制 单个段的重新传输尝试次数。它表明 当到达R1时,TCP应通知应用程序 段,并在到达R2时关闭连接。[RFC1122]也 定义R1(3次重传)和R2(100)的建议值 秒),注意SYN段的R2应至少为3 分钟。”

服务器和客户端之间可能有很多设备;你不太可能控制全部(当然,除非是局域网)。由于目前没有跨应用程序和网关商定超时设置的标准;对于防火墙,最好定期发送“保持活动”数据。此外,许多其他问题可能会中断连接,同样,应用程序也可能失败。因此,keep-alive heartbeat实现有助于创建一个健壮的应用程序,使连接保持打开状态并及时发现问题

心碎 根据应用程序的不同,我通常使用1到5秒之间的心跳间隔。客户端统计丢失的心跳,并在信号关闭时做出相应响应(例如,退回到AJAX轮询、提醒用户、重新启动脚本等)。请记住,发布服务器-订阅服务器消息不会排队。如果订阅者错过了它,它就错过了它。如果您希望服务器能够确认接收和客户端连接状态,则需要额外的通信过程。如果客户端宕机一段时间,则无法确定是否已收到所有消息。该系统具有良好的性能和健壮的应用程序设计

“心跳解决了知道同伴是否活着的问题 死。这不是ZeroMQ特有的问题。TCP超时时间较长 (30分钟左右),这意味着不可能知道 是否有同龄人死亡、断开连接或在周末前往 布拉格有一箱伏特加,一个红头发,还有一大笔开支。”

好的,下面是一个使用您的代码的代码示例:

Server.php

<?php
$context = new ZMQContext();
$publisher = new ZMQSocket($context, ZMQ::SOCKET_PUB);
$publisher->bind("tcp://*:5563");

while (true) {
    sleep (300);
    $publisher->send("A", ZMQ::MODE_SNDMORE);
    $publisher->send("We don't want to see this");
    $publisher->send("B", ZMQ::MODE_SNDMORE);
    $publisher->send("We would like to see this");
}
<?php

$context = new ZMQContext();
$subscriber = new ZMQSocket($context, ZMQ::SOCKET_SUB);
$subscriber->connect("tcp://localhost:5563"); // This is the setting for local server.php. I changed it for server.php at remote.php 
$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, "B");

while (true) {
    $address = $subscriber->recv();
    $contents = $subscriber->recv();
    printf ("[%s] %s%s", $address, $contents, PHP_EOL);
<?php

$context = new ZMQContext();
$publisher = new ZMQSocket($context, ZMQ::SOCKET_PUB);
$publisher->bind("tcp://*:5563");

$i = 0; // Iteration counter to trigger message

while (true) {

    $publisher->send('HB'); // Distribute the heartbeat (all clients will subscribe)

    sleep (5); // Heartbeat interval

    $i++ // Clock that ticks up ~5 seconds at a time (alternatively,
    // you could set a variable to store the timestamp of the last time the 
    // messages (A & B) were sent and then check to see if 5 minutes has elapsed).

    if ($i >= 60) {
        // 300 seconds--or perhaps a hair more--have elapsed, send the messages

        $i = 0; // Rest the clock.

        $publisher->send("A", ZMQ::MODE_SNDMORE);
        $publisher->send("We don't want to see this");
        $publisher->send("B", ZMQ::MODE_SNDMORE);
        $publisher->send("We would like to see this");
    } // Don't forget to close if statement.    
}
<?php

$context = new ZMQContext();
$subscriber = new ZMQSocket($context, ZMQ::SOCKET_SUB);
$SERVERIP = 'Where is the server?'; // Make sure this is correct and no firewall!
$subscriber->connect("tcp://$SERVERIP:5563"); 

$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, "B");
$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, 'HB'); // Subscribe to the heartbeat

$heartMonitor = time(); // Time we started listening.

while (true) {
    $address = $subscriber->recv();

    $more = $subscriber->getSockOpt(ZMQ::SOCKOPT_RCVMORE); // See if this is a multipart message
    if ($more) {
    // Message has second part--normally there would be a loop for variable length messages.
    $contents = $subscriber->recv();
    }

    if ($address == 'HB') {
        // Message is the heartbeat, would send this to additional
        // application components and have them listen for heartbeat as well.
        $heartMonitor = time();  // Time last heartbeat received in seconds
    }else{
        // Message is your content message; Do stuff.
        printf ("[%s] %s%s", $address, $contents, PHP_EOL);
        $heartMonitor = time();  // It doesn't matter which message was just received, both confirm connection.
    }

    $timeout = 20; // At least 3 heartbeat signals were missed.

    if ($heartMonitor < (time() - $timeout)) {
        // Connection lost. Alert user, fallback, or attempt reconnect, etc. here.
        break;
    }
} // Don't forget to close while loop.

<?php

$context = new ZMQContext();
$subscriber = new ZMQSocket($context, ZMQ::SOCKET_SUB);
$SERVERIP = 'Where is the server?'; // Make sure this is correct and no firewall!
$subscriber->connect("tcp://$SERVERIP:5563"); 

$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, "B");
$subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, 'HB'); // Subscribe to the heartbeat

$heartMonitor = time(); // Time we started listening.

while (true) {
    $address = $subscriber->recv();

    $more = $subscriber->getSockOpt(ZMQ::SOCKOPT_RCVMORE); // See if this is a multipart message
    if ($more) {
    // Message has second part--normally there would be a loop for variable length messages.
    $contents = $subscriber->recv();
    }

    if ($address == 'HB') {
        // Message is the heartbeat, would send this to additional
        // application components and have them listen for heartbeat as well.
        $heartMonitor = time();  // Time last heartbeat received in seconds
    }else{
        // Message is your content message; Do stuff.
        printf ("[%s] %s%s", $address, $contents, PHP_EOL);
        $heartMonitor = time();  // It doesn't matter which message was just received, both confirm connection.
    }

    $timeout = 20; // At least 3 heartbeat signals were missed.

    if ($heartMonitor < (time() - $timeout)) {
        // Connection lost. Alert user, fallback, or attempt reconnect, etc. here.
        break;
    }
} // Don't forget to close while loop.