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;
}
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;
}
$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这行。
2020年11月27日 上午9:38 沙发
Swoole 的Websocket也出现了这个问题
多谢思路。。
2020年11月27日 上午9:49 1层
@DearY 不客气