【发布时间】:2012-02-03 09:36:06
【问题描述】:
我编写一个命令,然后通过 PHP 中的套接字从服务器读取。我们有 20 台服务器都运行一个 Node JS 脚本,它可以接收这些命令并执行它们。 Node JS 脚本将返回“ok”,PHP 回读该“ok”以确认命令已执行。
Node JS 脚本侦听端口 9000 并设置为 allow half open。
大多数情况下这都能正常工作,但是当发送大量命令时,我们偶尔会收到错误消息:
Contents: Message received back from socket was 'Unexpected token {'
Transport endpoint is not connected
传输端点消息提示我它没有成功连接。
我不是套接字方面的专家,所以我不知道我使用的实现是否“正确”。它在大多数情况下确实有效,但我知道有像 socket_bind 和 socket_listen 这样的功能可能会更好,尽管我不确定它们是做什么的。
这是我们正在使用的 PHP 代码。任何建议将不胜感激。
public function sendDaemonCommand($address, $template_id, $params = array()) {
$hostname = $this->getHostnameFromPrivateIP($address);
$port = 9000;
$command = array('template_id' => $template_id, 'params' => $params);
$command = json_encode($command);
// Create a TCP Stream socket
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
$this->mailError("Command Failed - " . $hostname, "Failed to create socket on " . $address . "\n\n" . socket_strerror(socket_last_error()) . "\n\nCommand:\n\n" . $command . "\n" . $this->functionTraceback());
return false;
}
// Connect to socket
if (socket_connect($sock, $address, $port) === false) {
$this->mailError("Command Failed - " . $hostname, "Failed to connect to socket on " . $address . "\n\n" . socket_strerror(socket_last_error($sock)) . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
socket_close($sock);
return false;
}
// Write command to socket
$_command = $command;
$length = strlen($_command);
while (true) {
$sent = socket_write($sock, $_command, $length);
if ($sent === false) {
$this->mailError("Command Failed - " . $hostname, "Failed to write command to socket on " . $address . "\n\n" . socket_strerror(socket_last_error($sock)) . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
socket_shutdown($sock, 2);
socket_close($sock);
return false;
}
if ($sent < $length) {
$_command = substr($_command, $sent);
$length -= $sent;
}
else {
break;
}
}
socket_shutdown($sock, 1);
// Read back from socket
if (($out = socket_read($sock, 1024)) !== false) {
@socket_shutdown($sock, 0);
$out = trim($out);
if ($out !== "ok") {
$this->mailError("Command Failed - " . $hostname, "Message received back from socket was '" . $out . "' on " . $address . "\n\n" . socket_strerror(socket_last_error($sock)) . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
socket_close($sock);
return false;
}
}
else {
$this->mailError("Command Failed - " . $hostname, "Failed to read from socket on " . $address . "\n\n" . socket_strerror(socket_last_error($sock)) . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
socket_shutdown($sock, 0);
socket_close($sock);
return false;
}
socket_close($sock);
return $out;
}
【问题讨论】:
-
好吧,你不应该使用 PHP 套接字连接到 Node.js,这在处理大量打开的连接时效率非常低。
-
您是否查看过 PHP 服务器端的 netstat ......也许您的本地端口用完了?
-
@alessioalex 我还能在 PHP 端使用什么?
-
@EugenRieck 不是节点 JS 应该是非阻塞的并且可以处理同时连接吗?
-
我说的是 PHP 端,而不是 JS 端:连接使用本地端口,并且 (localIP,localPort,remoteIP,remotePort) 元组必须是唯一的,所以当 NodeJS 处理 remoteIP 时, remotePort 的一部分,您可能会用完本地端口 - 套接字选项可以帮助您,但请通过查看 netstat 来帮助诊断!