Не работает чат на вебсокетах
Пытаюсь собрать чат на WebSocket в связке с js и php. Сначала пытался разобраться сам, но даже с помощью гайдов ничего не получается. Происходит переключение протоколов, сообщения встраиваются в код, но это никак не кооперируется между другими пользователями Вот js-код:
document.getElementById("button").addEventListener('click', function() {
let val = document.getElementById("text").value;
let chat = document.getElementById("chat");
let message = document.createElement("div");
let textMessage = document.getElementsByClassName("textMessage");
let userText = document.getElementsByClassName("userText");
message.className = "message";
let fname = JSON.stringify(document.cookie.match(/fname=.+?;/)).replace('fname=', '').replace(';', '').replace('["', '').replace('"]', '');
now = new Date();
nowHours = now.getHours();
nowMinutes = now.getMinutes();
let time = nowHours + ':' + nowMinutes;
message.innerHTML = "<div class\=\"textMessage\"><div class\=\"username\">" + fname + "</div><div class=\"userText\">"+ val +"</div></div><div class=\"time\">" + time + "</div>";
chat.append(message);
socket.send(message);
});
const socket = new WebSocket("ws://shop1.local:8090/server.php");
socket.onmessage = function() {
console.log("onmessage");
}
socket.onerror = function() {
let problems = document.createElement("div");
let buttons = document.getElementById('right-buttons');
problems.className = "problems";
problems.innerHTML = "<div>Проблемы с соединением</div><img src='/img/gif/giphy.gif'>";
buttons.append(problems);
}
socket.onopen = function() {
console.log("connection succesfull");
}
socket.onclose = function() {
socket.close();
}
Код на php:
<?php
class Chat
{
public function sendHeaders($headersText, $newSocket, $ipAddr, $port) {
$headers = array();
$tmpline = preg_split("/\r\n/", $headersText);
foreach ($tmpline as $line) {
$line = rtrim($line);
if(preg_match('/\A(\S+): (.*)\z/', $line, $mathes)) {
$headers[$mathes[1]] = $mathes[2];
}
}
$key = $headers['Sec-WebSocket-Key'];
$sKey = base64_encode(pack('H*', sha1($key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$strHeadr =
"HTTP/1.1 101 Switching Protocols \r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"Sec-WebSocket-Accept: $sKey\r\n\r\n"
;
socket_write($newSocket, $strHeadr, strlen($strHeadr));
}
public function newConnectionACK($client_ip_address) {
$message = "New client ". $client_ip_address.' connected';
$messageArray = [
"message" => $message,
"type" => "newConnectionACK"
];
$ask = $this->seal(json_encode($messageArray));
return $ask;
}
public function seal($socketData) {
$b1 = 0x81;
$length = strlen($socketData);
$header = "";
if($length <= 125) {
$header = pack('CC', $b1, $length);
}
else if($length > 125 && $length < 65536) {
$header = pack('CCn', $b1, 126, $length);
}
else if($length > 65536) {
$header = pack('CCNN', $b1, 127, $length);
}
return $header.$socketData;
}
public function send($message,$clientSocketArray) {
$messageLength = strlen($message);
foreach($clientSocketArray as $clientSocket) {
@socket_write($clientSocket, $message, $messageLength);
}
return true;
}
public function unseal($socketData) {
$length = ord($socketData[1]) & 127;
if($length == 126) {
$mask = substr($socketData,4,4);
$data = substr($socketData,8);
}
else if($length == 127) {
$mask = substr($socketData,10, 4);
$data = substr($socketData,14);
}
else {
$mask = substr($socketData,2, 4);
$data = substr($socketData,6);
}
$socketStr = "";
for($i = 0; $i < strlen($data); ++$i) {
$socketStr .= $data[$i] ^ $mask[$i%4];
}
return $socketStr;
}
public function createChatMessage($username, $messageStr) {
$message = $username . "<div>" . $messageStr . "</div>";
$messageArray = [
'type' =>'chat-box',
'message' => $message
];
return $this->seal(json_encode($messageArray));
}
public function newDisconectedACK($client_ip_address) {
$message = "Client ". $client_ip_address.' disconnected';
$messageArray = [
"message" => $message,
"type" => "newConnectionACK"
];
$ask = $this->seal(json_encode($messageArray));
return $ask;
}
}
?>
<?php
$ipAddr = 'shop1.local';
$port = 8090;
require_once 'chat.php';
$chat = new Chat();
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, 0, $port);
socket_listen($socket);
$clientSocketArray = array($socket);
while (true) {
$newSocketArray = $clientSocketArray;
$write = $except = null;
socket_select($newSocketArray, $write, $except,0,10);
if(in_array($socket, $newSocketArray)) {
$newSocket = socket_accept($socket);
$header = socket_read($newSocket, 2048);
$clientSocketArray[] = $newSocket;
$buf = 'message';
$chat->sendHeaders($header, $newSocket, $ipAddr, $port);
socket_getpeername($newSocket, $clientAddr);
$connectionACK = $chat->newConnectionACK($client_ip_address);
$chat->send($connectionACK,$clientSocketArray);
$newSocketArrayIndex = array_search($socket, $newSocketArray);
unset($newSocketArray[$newSocketArrayIndex]);
}
foreach($newSocketArray as $newSocketArrayResource) {
//1
while(socket_recv($newSocketArrayResource, $socketData, 1024, 0) >= 1) {
$socketMessage = $chat->unseal($socketData);
$messageObj = json_decode($socketMessage);
$chatMessage = $chat->createChatMessage($messageObj->chat_user, $messageObj->chat_message);
$chat->send($chatMessage,$clientSocketArray);
break 2;
}
///2
$socketData = @socket_read($newSocketArrayResource,1024, PHP_NORMAL_READ);
if($socketData === false) {
socket_getpeername($newSocketArrayResource, $client_ip_address);
$connectionACK = $chat->newDisconectedACK($client_ip_address);
$chat->send($connectionACK,$clientSocketArray);
$newSocketArrayIndex = array_search($newSocketArrayResource, $clientSocketArray);
unset($clientSocketArray[$newSocketArrayIndex]);
}
}
}
socket_close($socket);
?>