【发布时间】:2022-08-05 02:52:41
【问题描述】:
我想使用 JavaScript 和 PHP 建立一个套接字连接。 我使用 JS WebSocket 和 PHP Socket。 如果我在服务器上本地运行 PHP 脚本,那么它们会相互通信并建立连接(屏幕截图1)。
脚本在服务器上结束后,套接字不会立即可用(截图2)。
如果我使用 WebSocket 在浏览器中打开客户端脚本,则响应以难以理解的编码固定,并且在文本中不是恒定的,您可以在其上看到的只有请求来自的域名(屏幕截图3)。
端口:3000,在 80 和 443 上,套接字未 ping。
问题:浏览器以难以理解的编码响应的原因是什么,是否有必要在 JS 中为握手预先准备标题文本?我在这个论坛上读到,只能在 WebSocket([url], [protocol]) 中选择指定协议。
提前感谢您的建议。
例子:
回答:
▒▒▒▒▒2B▒~▒˼[▒▒p\'▒w▒
▒%▒▒c▒/ e▒O▒&ߍ▒▒L▒}▒▒4▒▒W▒▒▒4▒▒.▒▒ ▒▒̨̩▒+▒/▒,▒0▒▒▒▒/5▒▒▒domain.name▒
▒▒
# 3+)/▒ ▒~l▒se▒▒lxk▒aG?i▒i0
;m^eCG▒▒jI-+JJ
ih2**▒
==============================
服务器代码:
<?php
// set some variables
$url_site = \'domain.name\';
$host = gethostbyname($url_site);
$port = getservbyname(\'https\', \'tcp\');
$port = 3000;
// don\'t timeout!
set_time_limit(0);
$flag_handshake = false;
$client = null;
header(\"Content-Type:application/javascript; charset=utf-8\");
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die(\"Could not create socket\\n\");
echo serialize($socket).\" socket_create...\\n\\n\";
// bind socket to port
$result = socket_bind($socket, $host, $port) or die(\"Could not bind to socket\\n\");
echo serialize($socket).\" socket_bind...\\n\\n\";
// start listening for connections
$result = socket_listen($socket, 0) or die(\"Could not set up socket listener\\n\");
echo serialize($socket).\" socket_listen...\\n\\n\";
echo \"Ready to receive on wss://$host:$port/ ...\\n\";
do {
if (!$client) {
// accept incoming connections
// client another socket to handle communication
$client = socket_accept($socket) or die(\"Could not accept incoming connection\\n\");
echo \"Client << $client >> has connected.\\n\";
}
$bytes = @socket_recv($client, $data, 2048, 0);
if ($flag_handshake == false) {
if ((int)$bytes == 0)
continue;
print(\"Handshaking headers from client: \". mb_detect_encoding($data) .\" - \". $data .\"\\n\");
echo $client .\" -->>LEN<<-- \". $bytes;
if (handshake($client, $data, $socket)) {
$flag_handshake = true;
}
}
elseif($flag_handshake == true) {
if ($data != \"\") {
$decoded_data = unmask($data);
print(\"< \". $decoded_data .\"\\n\");
$response = strrev($decoded_data);
socket_write($client, encode($response));
print(\"> \". $response .\"\\n\");
socket_close($client);
$client = null;
$flag_handshake = false;
}
}
} while (true);
// close sockets
socket_close($client);
socket_close($socket);
function handshake($client, $headers, $socket) {
print(\" [ HEADER: \" . $headers .\" ] \");
if (preg_match(\"/Sec-WebSocket-Version: (.*)\\r\\n/\", $headers, $match)) {
$version = $match[1];
//$version = 333;
} else {
print(\" [ The client doesn\'t support WebSocket ] \");
return false;
//$version = 111;
}
if ($version == 13) {
// Extract header variables
if (preg_match(\"/GET (.*) HTTP/\", $headers, $match))
$root = $match[1];
if (preg_match(\"/Host: (.*)\\r\\n/\", $headers, $match))
$host = $match[1];
if (preg_match(\"/Origin: (.*)\\r\\n/\", $headers, $match))
$origin = $match[1];
if (preg_match(\"/Sec-WebSocket-Key: (.*)\\r\\n/\", $headers, $match))
$key = $match[1];
$acceptKey = $key.\'258EAFA5-E914-47DA-95CA-C5AB0DC85B11\';
$acceptKey = base64_encode(sha1($acceptKey, true));
$upgrade = \"HTTP/1.1 101 Switching Protocols\\r\\n\".
\"Upgrade: websocket\\r\\n\".
\"Connection: Upgrade\\r\\n\".
\"Sec-WebSocket-Accept: $acceptKey\".
\"\\r\\n\\r\\n\";
socket_write($client, $upgrade);
return true;
} else {
print(\"WebSocket version 13 required (the client supports version {$version})\");
return false;
}
}
function unmask($payload) {
$length = ord($payload[1]) & 127;
if ($length == 126) {
$masks = substr($payload, 4, 4);
$data = substr($payload, 8);
}
elseif($length == 127) {
$masks = substr($payload, 10, 4);
$data = substr($payload, 14);
}
else {
$masks = substr($payload, 2, 4);
$data = substr($payload, 6);
}
$text = \'\';
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i % 4];
}
return $text;
}
function encode($text) {
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if ($length <= 125)
$header = pack(\'CC\', $b1, $length);
elseif($length > 125 && $length < 65536)$header = pack(\'CCS\', $b1, 126, $length);
elseif($length >= 65536)
$header = pack(\'CCN\', $b1, 127, $length);
return $header.$text;
}
?>
==============================
客户端代码:
<html>
<head>
<meta charset=\"UTF-8\">
</head>
<script>
var socket = new WebSocket(\'wss://domain.name:3000/\');
console.log(\'New socket \');
console.log(socket);
console.log(\'Let`s open \');
// Open the socket
socket.onopen = function(event) {
console.log(event);
var msg = \'I am the client.\';
console.log(\'> \' + msg);
// Send an initial message
socket.send(msg);
// Listen for messages
socket.onmessage = function(event) {
console.log(\'< \' + event.data);
};
// Listen for socket closes
socket.onclose = function(event) {
console.log(\'Client notified socket has closed\', event);
};
// To close the socket....
socket.close()
};
socket.onmessage = function(event) {
console.log(`[message] Data received from server: ${event.data}`);
};
socket.onclose = function(event) {
if (event.wasClean) {
console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
console.log(\'[close] Connection died\');
}
};
socket.onerror = function(error) {
console.log(`[error] ${error.message}`);
};
</script>
<body>
<p>Please check the console log of your browser.</p>
</body>
</html>
=============================
标签: javascript php websocket