我在服务器端使用MySQL
和PHP
编写了一个数据库应用程序,在客户端使用Flex
。我使用php套接字让它在数据库发生变化时自动更新所有客户端。
整个系统都在游泳,但是插座似乎不时响应。奇怪的是连接仍然很好 - 客户端执行的任何更改都已实现,但套接字不会广播该消息。套接字文件没有抛出任何错误(但是当我从套接字运行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);
}
?>
答案 0 :(得分:0)
由于正在使用的套接字似乎阻塞,因此在读取请求的数据量之前,对socket_recv()
的调用可能不会返回。并且这不会处理任何其他读取套接字,包括accecpting套接字。
要解决此问题,请使用socket_set_nonblock()
使套接字解除阻止。请注意,在非阻塞套接字上调用socket_recv()
可能会返回读取的字节数少于请求的字节数,因此应为每个套接字跟踪读取的数据量。