WebSockets 在 Amazon ec2 环境中不起作用

Posted

技术标签:

【中文标题】WebSockets 在 Amazon ec2 环境中不起作用【英文标题】:WebSockets not working on Amazon ec2 environment 【发布时间】:2013-10-09 05:43:49 【问题描述】:

我通过 websockets 借助此链接 "http://www.flynsarmy.com/2012/02/php-websocket-chat-application-2-0/" 制作了一个聊天应用程序。虽然它在我自己的开发服务器中运行良好,但是当我将它托管在我公司的 amazon ec2 服务器上时,它显示错误: " Firefox 无法在 ws://external ip for amazon:port/ 上建立与服务器的连接"

我在尝试将客户端连接到服务器时使用服务器的外部 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 库来运行我的聊天。它的工作非常顺利。

【问题讨论】:

【参考方案1】:

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

我建议看看Ratchet。这是最新的并且经过良好测试。

【讨论】:

嗨,oberstet。感谢回复。但是我的项目正在本地主机以及我的开发服务器上运行。在 chrome、firefox 和 ie10 上。它只是不适用于亚马逊 ec2。另外,我必须从头开始编写代码,我无法使用任何我看不到的外部库。 您是否使用端口

以上是关于WebSockets 在 Amazon ec2 环境中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

亚马逊ec2上的Websockets连接失败

amazon ec2 是个啥东西

Amazon 实例 Ec2 连接超时

在 Amazon EMR 4.1 和 Amazon EC2 上安装 Impala

无法与在 EC2 上运行的 Laravel Websockets 建立连接

sh ec2-get-tag函数,用于在Amazon EC2中检索标记值