我已经通过websockets制作了一个聊天应用程序,借助此链接"http://www.flynsarmy.com/2012/02/php-websocket-chat-application-2-0/"。虽然它在我自己的开发服务器中运行良好,但是当我将其托管在我公司的 Amazon ec2 服务器上时,它显示错误:" Firefox 无法在 Amazon:port/ws://external IP 上与服务器建立连接">
我在尝试将客户端连接到服务器时使用服务器的外部 IP,在执行服务器文件时,我正在使用服务器的亚马逊内部 IP。我还在我的 ec2 中放置了一个转发规则,使我的端口可以在 tcp 和 udp 中访问。
我还检查了亚马逊服务器的 ELB,我的服务器没有 ELB。
它仍然不起作用。这是我服务器文件的代码的一部分,其中创建了套接字并连接了客户端。
if (isset($this->wsRead[0])) return false;
if (!$this->wsRead[0] = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) {
return false;
}
if (!socket_set_option($this->wsRead[0], SOL_SOCKET, SO_REUSEADDR, 1)) {
socket_close($this->wsRead[0]);
return false;
}
if (!socket_bind($this->wsRead[0], $host, $port)) {
socket_close($this->wsRead[0]);
return false;
}
if (!socket_listen($this->wsRead[0], 10)) {
socket_close($this->wsRead[0]);
return false;
}
$write = array();
$except = array();
$nextPingCheck = time() + 1;
while (isset($this->wsRead[0])) {
$changed = $this->wsRead;
$result = socket_select($changed, $write, $except, 1);
if ($result === false) {
socket_close($this->wsRead[0]);
return false;
}
elseif ($result > 0) {
foreach ($changed as $clientID => $socket) {
if ($clientID != 0) {
// client socket changed
$buffer = '';
$bytes = @socket_recv($socket, $buffer, 4096, 0);
//$this->log($buffer);
if ($bytes === false) {
// error on recv, remove client socket (will check to send close frame)
$this->wsSendClientClose($clientID, self::WS_STATUS_PROTOCOL_ERROR);
}
elseif ($bytes > 0) {
// process handshake or frame(s)
//$this->log("hi".$buffer);
if (!$this->wsProcessClient($clientID, $buffer, $bytes)) {
$this->wsSendClientClose($clientID, self::WS_STATUS_PROTOCOL_ERROR);
}
}
else {
// 0 bytes received from client, meaning the client closed the TCP connection
$this->wsRemoveClient($clientID);
}
}
else {
// listen socket changed
$client = socket_accept($this->wsRead[0]);
if ($client !== false) {
// fetch client IP as integer
$clientIP = '';
$result = socket_getpeername($client, $clientIP);
//$this->log($clientIP);
$clientIP = ip2long($clientIP);
//$this->log($clientIP);
if ($result !== false && $this->wsClientCount < self::WS_MAX_CLIENTS && (!isset($this->wsClientIPCount[$clientIP]) || $this->wsClientIPCount[$clientIP] < self::WS_MAX_CLIENTS_PER_IP)) {
$this->wsAddClient($client, $clientIP);
}
else {
socket_close($client);
}
}
}
}
}
if (time() >= $nextPingCheck) {
$this->wsCheckIdleClients();
$nextPingCheck = time() + 1;
}
}
return true; // returned when wsStopServer() is called
我认为这个问题围绕着无法选择创建的套接字的socket_select((函数。如何让它工作?请帮忙,因为即使经过多次尝试,我也无法解决这个问题。
更新
我发现这个问题是由于亚马逊上的旧版本的python引起的。所以我将 python 版本更改为 2.6/2.7
我也替换了 socket.io 库来运行我的聊天。它的工作非常顺利。
您使用的 WebSocket 实现似乎实现了已弃用的 Hixie-76 版本的 WebSocket 协议,Firefox(以及 Chrome 和其他协议(不再支持该协议。
我建议看看瑞奇。这是最新的,并且经过了良好的测试。