websocket握手连接失败,报错Response must not include ‘Sec-WebSocket-Protocol’ header if not present in request: chat

websocket连接失败,报错:WebSocket connection to 'ws://127.0.0.1:8888/' failed: Error during WebSocket handshake: Response must not include 'Sec-WebSocket-Protocol' header if not present in request: chat

遇到这个问题怎么解决呢?有两种方法
一、第一种方法是在后端php那里去掉Sec-WebSocket-Protocol这一行,并且在前面一行再加一个"\r\n"

function handleShake($request){
    preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$request,$match);
    $key = $match[1];
    $new_key = base64_encode(sha1($key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11',true));

    $response = "HTTP/1.1 101 Switching Protocols\r\n";
    $response .= "Upgrade: websocket\r\n";
    $response .= "Connection: Upgrade\r\n";
    $response .= "Sec-WebSocket-Accept: $new_key\r\n\r\n";//在这行多加一个"\r\n"
    //$response .= "Sec-WebSocket-Protocol: chat\r\n\r\n";//注释掉这行

    return $response;
   

}

后端完整代码如下:

<?php
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);

socket_set_option($socket,SOL_SOCKET,SO_REUSEADDR,true);

socket_bind($socket,0,8888);

socket_listen($socket);

while(true){
    $conSock = socket_accept($socket);

    $request = socket_read($conSock,1024);
    $response = handleShake($request);

    socket_write($conSock,$response,strlen($response));

    $res = socket_read($conSock,1024);

    echo decode($res);

    $str = encode('hello client'); 

    socket_write($conSock,$str,strlen($str));


}



function encode($msg) {
        $frame = [];
        $frame[0] = '81';
        $len = strlen($msg);
        if ($len < 126) {
            $frame[1] = $len < 16 ? '0' . dechex($len) : dechex($len);
        } else if ($len < 65025) {
            $s = dechex($len);
            $frame[1] = '7e' . str_repeat('0', 4 - strlen($s)) . $s;
        } else {
            $s = dechex($len);
            $frame[1] = '7f' . str_repeat('0', 16 - strlen($s)) . $s;
        }
        $data = '';
        $l = strlen($msg);
        for ($i = 0; $i < $l; $i++) {
            $data .= dechex(ord($msg{$i}));
        }
        $frame[2] = $data;
        $data = implode('', $frame);
        return pack("H*", $data);
}



function handleShake($request){
    preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$request,$match);
    $key = $match[1];
    $new_key = base64_encode(sha1($key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11',true));

    $response = "HTTP/1.1 101 Switching Protocols\r\n";
    $response .= "Upgrade: websocket\r\n";
    $response .= "Connection: Upgrade\r\n";
    $response .= "Sec-WebSocket-Accept: $new_key\r\n\r\n";
    //$response .= "Sec-WebSocket-Protocol: chat\r\n\r\n";

    return $response;
   

}

function decode($buffer) {
        $decoded = '';
        $len = ord($buffer[1]) & 127;
        if ($len === 126) {
            $masks = substr($buffer, 4, 4);
            $data = substr($buffer, 8);
        } else if ($len === 127) {
            $masks = substr($buffer, 10, 4);
            $data = substr($buffer, 14);
        } else {
            $masks = substr($buffer, 2, 4);
            $data = substr($buffer, 6);
        }
        for ($index = 0; $index < strlen($data); $index++) {
            $decoded .= $data[$index] ^ $masks[$index % 4];
        }
        return $decoded;
}

二、第二种方法是在前端websocket连接里面,加一个参数'chat',第二种方法不需要在php中去掉Sec-WebSocket-Protocol这行。

<script>
    const socket = new WebSocket('ws://127.0.0.1:8888','chat');
    console.log(socket)
    socket.onopen = function(){

       console.log('connected success');
       socket.send('hello server');
    }

    socket.onmessage  = function(e){
        console.log(e.data)
    }
</script>
  • 2
  • 3,331 views
    A+
发布日期:2020年02月15日  所属分类:php

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:2   其中:访客  1   博主  1

  1. DearY 0

    Swoole 的Websocket也出现了这个问题
    多谢思路。。

    • 志博

      @DearY 不客气