Web-Socket Timeout
I'll go straight to the heart of the problem. We received a task to raise web sockets. Working on OpenServer shared via domain http://user-ks-7.hldns.ru. The problem is that when working on with the address in the js script on localhost:the port works fine, and as soon as the address changes to the server one, it immediately goes to the WebSocket connection to 'ws://user-ks-7.hldns.ru:30434/web-socket/server.php' failed: Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT. I attach all the codes below, both the server one with the "library", and the script working on the client. At the moment, the application serves as a chat and was created only for testing and working with sockets for the first time. On request, I can attach the OpenServer settings, as well as the router settings, if necessary.
var $ = (id) => {return document.getElementById(id)}
function messageSend(message){
$('chat').append(message+'\n');
}
window.onload = () => {
// var socket = new WebSocket('ws://localhost:30434/web-socket/server.php')
var socket = new WebSocket('ws://user-ks-7.hldns.ru:30434/web-socket/server.php')
// var socket = new WebSocket('ws://user-ks-7.hldns.ru:8080/web-socket/server.php')
socket.onopen = () =>{
messageSend('Соединение установлено ')
}
socket.onerror = (e) =>{
messageSend('Ошибка соединения' + (e.message ? e.message : ''))
}
socket.onclose = () =>{
messageSend(`Закрытие соединения `)
}
socket.onmessage = () =>{
var data = JSON.parse(event.data)
console.log(`Сообщение ${data.message}`)
console.log(`Тип сообщения ${data.type}`)
messageSend(data.type + ' - ' + data.message)
}
$('btn_send').addEventListener('click', () =>{
console.log($('chat_message').value)
console.log($('chat_user').value)
var message = {
chat_message:$('chat_message').value,
chat_user:$('chat_user').value,
}
console.log(message)
$('chat_user').setAttribute('type','hidden')
socket.send(JSON.stringify(message))
return false
})
}
#chat{
border: 1px solid grey;
padding: 10px;
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Chat</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<form id="chat" onsubmit='return false'>
<div class="chat-result" id="chat-result">
<input type="text" name="chat-user" id="chat_user" placeholder="Name">
<input type="text" name="chat-message" id="chat_message" placeholder="Message">
<input type="submit" value="Send" id='btn_send'>
</div>
</form>
</body>
</html>
server.php
<?php
define('PORT',"30434");
require_once ("class/chat.php");
$chat = new Chat();
$socket = socket_create(AF_INET, SOCK_STREAM,SOL_TCP);
if(!$socket){
echo "Ошибка создания сокета\n";
}else{
echo "Сокет успешно создан\n";
}
$err = socket_set_option($socket, SOL_SOCKET,SO_REUSEADDR, 1);
if(!$err){
echo "Ошибка установки настроек сокета\n";
}else{
echo "Сокет настроен успешно\n";
}
$err = socket_bind($socket,0, PORT);
if(!$err){
echo "Ошибка согласования сокета с портом\n";
}else{
echo "Cогласование сокета с портом успешно\n";
}
socket_listen($socket);
$clientSocketArray = array($socket);
while(true) {
$newSocketArray = $clientSocketArray;
$nullA = [];
socket_select($newSocketArray,$nullA, $nullA,0,10);
if(in_array($socket, $newSocketArray)) {
$newSocket = socket_accept($socket);
$clientSocketArray[] = $newSocket;
$header = socket_read($newSocket, 1024);
$chat->sendHeaders($header,$newSocket,'user-ks-7.hldns.ru/web-socket',PORT);
socket_getpeername($newSocket, $client_ip_address);
$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->reconstruction($socketData);
$messageObj = json_decode($socketMessage);
$chatMessage = $chat->createChatMessage($messageObj->chat_user, $messageObj->chat_message);
echo $chatMessage;
$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]);
}
}
}
echo 'Закрытие сокета';
socket_close($socket);
Class/chat.php
class Chat{
public function sendHeaders($headerText,$newSocket,$host,$port){
$headers = array();
$tmpString = preg_split('/\r\n/',$headerText);
foreach($tmpString as $string){
$string = rtrim($string);//Избавляемся от пробелов в строке
if(preg_match('/\A(\S+): (.*)\z/',$string,$tmpHead)){
$headers[$tmpHead[1]] = $tmpHead[2];
}
}
$tmpKey = $headers['Sec-WebSocket-Key'];
$key = base64_encode(pack('H*',sha1($tmpKey.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$strHeader = "HTTP/1.1 101 Switching Protocols \r\n".
"Upgrade: websocket\r\n".
"Connection: Upgrade\r\n".
"WebSocket-Origin: $host\r\n".
"WebSocket-Location: ws://$host:$port/chat/server.php\r\n".
"Sec-WebSocket-Accept: $key\r\n\r\n";
socket_write($newSocket,$strHeader,strlen($strHeader));
}
public function newConnectionACK($client_ip_addr){
$message = "New client ".$client_ip_addr." connected ";
$messageArray = [
// 'message' => $message,
'message' => $message,
'type' => 'NewConnect:27'
];
$ask = $this->transform(json_encode($messageArray)); //!tranform ebat
return $ask;
}
public function transform($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 reconstruction($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,$messageContent){
$message = 'Юзер : '.$username .' отправил : '.$messageContent;
$messageArray = [
'message' => $message,
'type' => 'NewMessage:74',
];
$request = $this->transform(json_encode($messageArray));
return $request;
}
public function newDisconectedACK($client_ip_address) {
$message = "Client ". $client_ip_address.' disconnected';
$messageArray = [
"message" => $message,
"type" => "NewDisconnect:83"
];
$ask = $this->transform(json_encode($messageArray));
return $ask;
}
}