V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Dive into HTML5
http://diveintohtml5.org/
alantx
V2EX  ›  HTML

IE 下的 WebSocket 的问题

  •  1
     
  •   alantx · 2016-04-02 21:16:34 +08:00 · 3815 次点击
    这是一个创建于 3141 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我用 php 写了个 socket 服务端,然后在火狐运行客户端握手成功后,
    1.用 send()函数发送信息给服务端
    2.服务端 socket__read 提取信息
    3.再用 socket__write 返回信息可以触发客户端的 onmessage 事件。

    而在 ie 和 chrome 下却触发不了 onmessage 事件,
    1.首先 send()发送信息到服务端
    2.socket__select 获得套接字 A , socket__read 取得信息
    3.再将同样的信息用 socket__write 返回给套接字 A ,之后再监听套接字 A ,在火狐下这样就会结束
    但是在 ie 下 socket__select 会再次获得套接字 A ,接着重复取得以及返回信息最后监听套接字 A 。 当然还没完, socket__select 还会获得套接字 A ,在经历前两次的 read 和 write 后,这次 socket__read 取得的信息会是空值。

    顺便一提,在 ie 下服务端第一次执行 socket__write 的返回值是 int(10),这是正常的,而第二次执行 write 会返回 int(32),因为是在 cmd 下运行 php 文件的, socket__read 取得的信息显示为乱码(握手协议倒是显示正常),所以我不知道第二次 socket__write 返回的信息是什么。
    为什么会这样?明明握手都可以成功来着, onopen 事件已经触发了,为什么到 onmessage 的时候就出现问题!

    第 1 条附言  ·  2016-04-02 22:38:00 +08:00
    如果单凭以上的信息无法找到问题的话,一下是我的代码
    html:
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <meta name="description" content="test">
    <meta name="keywords" content="test">
    <meta name="renderer" content="ie-stand">
    <title>test</title>
    </head>
    <body>
    <p id="p" style="text-align:center"></p>
    <button onclick="send()">Send</button>
    </body>
    <script>
    socket=new WebSocket("ws://localhost:1199");
    socket.onopen=function(){document.querySelector("#p").innerHTML="ws";}
    socket. onmessage=function(e){document.querySelector("#p").innerHTML=e.data;}
    function send(){socket.send("test");}
    </script>
    </html>

    php:
    <?
    $master=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
    socket_set_option($master,SOL_SOCKET,SO_REUSEADDR,1);
    socket_bind($master,"localhost",1199);
    socket_listen($master,5);
    $sockets[]=$master;$w=NULL;$r=NULL;
    for($i=0;;$i++){
    $sockets_copy=$sockets;echo"select_bf: ";var_dump($sockets_copy);echo"\n";
    socket_select($sockets_copy,$r,$w,NULL);
    foreach($sockets_copy as $socket){
    if($socket==$master){echo"true\n";$client=socket_accept($socket);array_push($sockets,$client);}
    else{echo"false: ";var_dump($socket);echo"\n";
    $buffer=socket_read($socket,1024);echo"buffer:".$buffer."\n";
    if($buffer==""){echo"true_1\n";sort($sockets);$num=array_keys($sockets,$socket);array_splice($sockets,$num[0],1);socket_close($socket);}
    else{echo"false_1\n";
    if(preg_match("/(?<=Sec-WebSocket-Key:).*/",$buffer,$match)){
    echo"true_2\n";
    $str="HTTP/1.1 101 Switching Protocols\r\n"."Upgrade: websocket\r\n"."Connection: Upgrade\r\n"."Sec-WebSocket-Accept: ".base64_encode(sha1(trim($match[0]).'258EAFA5-E914-47DA-95CA-C5AB0DC85B11',true))."\r\n\r\n";
    echo"str:".$str."\n";socket_write($socket,$str);
    }
    else{echo"false_2: ";$s_w=socket_write($socket,$buffer);var_dump($s_w);echo"\n";}
    }
    }
    }
    }
    ?>
    1 条回复    2020-09-11 14:18:34 +08:00
    jonychen1
        1
    jonychen1  
       2020-09-11 14:18:34 +08:00
    很多低版本的浏览器对 websocket 的支持不是很好,这时候就需要做下向下的兼容,一般是混合采用 websocket+polling 这些来做,还是有些麻烦的。在正式项目中可以考虑采用第三方推送框架比如 GoEasy,这些兼容都是做好了的,也支持 wss 、心跳、重连机制,地址: https://www.goeasy.io/
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2848 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 13:09 · PVG 21:09 · LAX 05:09 · JFK 08:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.