WebSockets无法在Amazon ec2环境中运行

时间:2013-10-09 05:43:50

标签: amazon-ec2 websocket phpwebsocket

我已经通过websockets帮助这个链接做了一个聊天应用程序" http://www.flynsarmy.com/2012/02/php-websocket-chat-application-2-0/" 。虽然它在我自己的开发服务器中运行得很好,但是当我在我公司的amazon ec2服务器上托管时,它显示错误: " Firefox无法在ws://外部ip建立与服务器的连接,以便亚马逊:端口/"

在尝试将客户端连接到服务器和服务器的内部IP时,我正在使用服务器的外部IP,以便在执行服务器文件时使用amazon。我还在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库来运行我的聊天。它的工作非常顺利。

1 个答案:

答案 0 :(得分:0)

您正在使用的WebSocket实现似乎实现了WebSocket协议的弃用的Hixie-76版本,Firefox(以及Chrome和其他人)不再支持该版本。

我建议看看Ratchet。这是最新的,经过充分测试。