1

我已经在服务器端和客户端使用MySQLand编写了一个数据库应用程序。我使用 php 套接字让它在对数据库进行更改时自动更新所有客户端。PHPFlex

整个系统运行顺畅,但套接字似乎时不时停止响应。奇怪的是连接仍然很好——客户端执行的任何更改都已实现,但套接字不会广播消息。套接字文件没有抛出任何错误(尽管当我从套接字运行 error_log 时会出现这些消息)。服务器上套接字的内存使用不会改变,也不会发送断开信号。更奇怪的是,大约半小时左右后,套接字最终再次开始工作。如果我重新启动也可以解决问题的套接字。

我正在研究一个 hacky 解决方案,允许客户端在套接字变得无响应时重新启动它,但这并不令人满意并且容易出错。我真正想要的是了解为什么会发生这种情况。在一定数量的连接后,套接字是否会以某种方式“饱和”?我应该做些什么来清理套接字服务器吗?我尝试了三种不同的物理服务器(一台本地服务器和两台在线服务器)并且发生了同样的事情,所以肯定是我。

我觉得我做错了一些基本的事情。这是我用于套接字服务器的代码(它是 Raymond Fain 在 kirupa.com 上编写的稍微修改过的套接字版本,所以我将他的原始评论留在了顶部):

#!/usr/bin/php -q
<?php
/*
Raymond Fain
Used for PHP5 Sockets with Flash 8 Tutorial for Kirupa.com
For any questions or concerns, email me at ray@obi-graphics.com
or simply visit the site, www.php.net, to see if you can find an answer.
*/

//ini_set('display_errors',1);
//ini_set('display_startup_errors',1);
error_reporting(E_ALL);
ini_set('error_log', 'socket_errors.log');
ini_set('log_errors', 'On');
ini_set('display_errors', 'Off');

set_time_limit(0);

ob_implicit_flush();

error_log('testing');

$address = 'xxx.xxx.xx.xx';
$port = xxxxx;

function send_Message($allclient, $socket, $buf)
{
    $buf = str_replace("\0","",$buf);
    //echo "<mbFeed>$buf</mbFeed>\n\0";
    foreach($allclient as $client)
    {
        socket_write($client, "<mbFeed>$buf</mbFeed>\n\0");
    }
}


echo "connecting...
";
//---- Start Socket creation for PHP 5 Socket Server -------------------------------------

if (($master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0)
{
    echo "socket_create() failed, reason: " . socket_strerror($master) . "\n";
}

socket_set_option($master, SOL_SOCKET,SO_REUSEADDR, 1);


if (($ret = socket_bind($master, $address, $port)) < 0)
{
    echo "socket_bind() failed, reason: " . socket_strerror($ret) . "\n";
}

echo 'socket bind successfull.
';


if (($ret = socket_listen($master, 5)) < 0)
{
    echo "socket_listen() failed, reason: " . socket_strerror($ret) . "\n";
}

$read_sockets = array($master);

echo "connected.";

//---- Create Persistent Loop to continuously handle incoming socket messages ---------------------
while (true)
{ 
    $changed_sockets = $read_sockets;
    $num_changed_sockets = socket_select($changed_sockets, $write = NULL, $except = NULL, NULL);
    foreach($changed_sockets as $key => $socket)
    {
        if ($socket == $master)
        {
            if (($client = socket_accept($master)) < 0)
            {
                echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
                continue;
            } 
            else
            {
                array_push($read_sockets, $client);
            }
        }
        else
        {
            $bytes = socket_recv($socket, $buffer, 8192, 0);

            if ($bytes == 0)
            {
                unset($read_sockets[$key]);
                unset($changed_sockets[$key]);
                socket_close($socket);
            }
            else
            {
                $allclients = $read_sockets;
                array_shift($allclients);
                //any messages starting with ::: are not to be broadcast, and may be used for other things. This message
                //usually comes from the client.
                if (substr($buffer, 0, 3) == ":::") handleSpecial(substr($buffer, 3));
                else
                {
                    //otherwise the message comes from a php file that will be closed, so the socket needs to be closed.
                    unset($read_sockets[$key]);
                    unset($changed_sockets[$key]);
                    socket_close($socket);
                    send_Message($allclients, $socket, $buffer);
                }
            }
        }
    }
}

function handleSpecial($message)
{
    error_log($message);
}
?>
4

1 回答 1

0

由于正在使用的套接字似乎阻塞了调用,socket_recv()因此在读取请求的数据量之前可能不会返回。并且这不处理任何其他读取套接字,包括接受套接字。

为了解决这个问题socket_set_nonblock(),让套接字畅通无阻。请注意,socket_recv()对非阻塞套接字的调用可能返回读取的字节数少于请求的字节数,因此应跟踪每个套接字的读取数据量。

于 2012-11-16T18:18:42.683 回答