Więc Idea stoi za setInterval i Sockets, setInterval jest obsługiwany w większości przeglądarek, a javascript WbsocketApi jest obsługiwany w prawie każdym przeglądarce.
Krótki przegląd: setInterval () - funkcja ta zachowuje się, gdy komputer znajduje się w trybie uśpienia / zawieszenia / hibernacji, jest wstrzymany, a po przejściu w tryb czuwania wznawia się.
Poniższy kod wykonuje następujące czynności, na początku (może w tym samym czasie, ale) uruchamia php server_socket nasłuchując połączeń,
niż javascript websocket api wysyła bieżący znacznik czasu w uniksowych znacznikach czasu w milisekundach co 2 sekundy, możesz mieć 1 sekundę, to zależy od Ciebie.
po tym czasie gniazdo serwera php dostaje ten czas i sprawdza, czy ma coś takiego jak poprzedni czas do porównania, kiedy kod jest tworzony po raz pierwszy, php nie ma nic takiego jak poprzedni czas, aby porównać go z czasem, który został wysłany z javascript websocket, więc php oszczędza tylko ten czas w sesji o nazwie „prev_time” i czeka na kolejne dane, które zostaną pobrane z gniazda javascript, więc tutaj zaczyna się drugi cykl. kiedy serwer php umieszcza nowe dane czasu z javascript WebsocketApi, sprawdza, czy ma coś takiego jak poprzedni czas, aby porównać je z nowo otrzymanymi danymi czasu, oznacza to, że php sprawdza, czy sesja o nazwie „prev_time” istnieje, ponieważ jesteśmy w drugim cyklu php odkrywa, że istnieje, chwyta swoją wartość i śledzi$diff = $new_time - $prev_time
, $ diff wyniesie 2 sekundy lub 2000 milisekund, ponieważ pamiętaj, że nasz cykl setInterval odbywa się co 2 sekundy, a format czasu, który wysyłamy, jest milisekundowy,
niż php sprawdza, if($diff<3000)
czy różnica jest mniejsza niż 3000, jeśli wie, że użytkownik jest aktywny, ponownie możesz manipulować tymi sekundami, jak chcesz, wybieram 3000, ponieważ możliwe opóźnienie w sieci jest prawie niemożliwe, ale wiesz, że zawsze jestem ostrożny, gdy przychodzi do sieci, więc kontynuujmy, gdy php ustali, że użytkownik jest aktywny. php po prostu resetuje sesję „prev_time”, której wartość $new_time
została nowo odebrana, i tylko w celach testowych wysyła wiadomość z powrotem do gniazda javascript,
ale jeśli $diff
jest większy niż 3000, oznacza to, że coś wstrzymało nasz interwał przedziału i istnieje tylko jeden sposób, aby to się wydarzyło i myślę, że już wiesz, co mówię, więc zgodnie z else
logiką ( if($diff<3000)
) możesz wylogować użytkownika, niszcząc określoną sesję i jeśli chcesz przekierować możesz wysłać trochę tekstu do gniazda javacript i stworzyć logikę, która będzie wykonywana w window.location = "/login"
zależności od tekstu, oto kod:
Najpierw jest to plik index.html tylko do załadowania javascript:
<html>
<body>
<div id="printer"></div>
<script src="javascript_client_socket.js"></script>
</body>
</html>
to jest javascript, nie jest naprawdę pięknie zakodowany, ale możesz dowiedzieć się, PRZECZYTAJ UWAGI, KTÓRE SĄ WAŻNE:
var socket = new WebSocket('ws://localhost:34237'); // connecting to socket
// Open the socket
socket.onopen = function(event) { // detecting when connection is established
setInterval(function(){ //seting interval for 2 seconds
var date = new Date(); //grabing current date
var nowtime = Date.parse(date); // parisng it in miliseconds
var msg = 'I am the client.'; //jsut testing message
// Send an initial message
socket.send(nowtime); //sending the time to php socket
},2000);
};
// Listen for messages
socket.onmessage = function(event) { //print text which will be sent by php socket
console.log('php: ' + event.data);
};
// Listen for socket closes
socket.onclose = function(event) {
console.log('Client notified socket has closed', event);
};
teraz tutaj jest częścią kodu php, nie martw się, jest też pełny kod, ale ta część jest właściwie tym, co robi wyżej wymienione zadania, spełnisz również inne funkcje, ale służą one do dekodowania i pracy z gniazdami javascript, więc jest to właściwe tutaj PRZECZYTAJ UWAGI, KTÓRE SĄ WAŻNE:
<?php
$decoded_data = unmask($data /* $data is actual data received from javascript socket */); //grabbing data and unmasking it | unmasking is for javascript sockets don't mind this
print("< ".$decoded_data."\n");
$response = strrev($decoded_data);
$jsTime = (int) $decoded_data; /* time sent by javascript in MILISECONDS IN UNIX FORMAT */
if (isset($_SESSION['prev_time'])) { /** check if we have stored previous time in the session */
$prev_time = (int) $_SESSION['prev_time']; /** grabbing the previous time from session */
$diff = $jsTime-$prev_time; /** getting the difference newly sent time and previous time by subtracting */
print("$jsTime - $prev_time = $diff"); /** printing the difference */
if($diff<3000){ /** checking if difference is less than 3 second if it is it means pc was not at sleep
*** you can manipulate and have for example 1 second = 1000ms */
socket_write($client,encode("You are active! your pc is awakend"));
$_SESSION['prev_time'] = $jsTime; /** saving newly sent time as previous time for future testing whcih will happen in two seconds in our case*/
}else { /** if it is more than 3 seconds it means that javascript setInterval function was paused and resumed after 3 seconds
** So it means that it was at sleep because when your PC is at sleep/suspended/hibernate mode setINterval gets pauesd */
socket_write($client,encode("You are not active! your pc is at sleep"));
$_SESSION['prev_time'] = $jsTime;
}
}else { /** if we have not saved the previous time in session save it */
$_SESSION['prev_time'] = $jsTime;
}
print_r($_SESSION);
?>
A oto pełny kod php:
<?php
//Code by: Nabi KAZ <www.nabi.ir>
session_abort();
// set some variables
$host = "127.0.0.1";
$port = 34237;
date_default_timezone_set("UTC");
// don't timeout!
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0)or die("Could not create socket\n");
// bind socket to port
$result = socket_bind($socket, $host, $port)or die("Could not bind to socket\n");
// start listening for connections
$result = socket_listen($socket, 20)or die("Could not set up socket listener\n");
$flag_handshake = false;
$client = null;
do {
if (!$client) {
// accept incoming connections
// client another socket to handle communication
$client = socket_accept($socket)or die("Could not accept incoming connection\n");
}
$bytes = @socket_recv($client, $data, 2048, 0);
if ($flag_handshake == false) {
if ((int)$bytes == 0)
continue;
//print("Handshaking headers from client: ".$data."\n");
if (handshake($client, $data, $socket)) {
$flag_handshake = true;
}
}
elseif($flag_handshake == true) {
/*
**** Main section for detectin sleep or not **
*/
if ($data != "") {
$decoded_data = unmask($data /* $data is actual data received from javascript socket */); //grabbing data and unmasking it | unmasking is for javascript sockets don't mind this
print("< ".$decoded_data."\n");
$response = strrev($decoded_data);
$jsTime = (int) $decoded_data; /* time sent by javascript in MILISECONDS IN UNIX FORMAT */
if (isset($_SESSION['prev_time'])) { /** check if we have stored previous time in the session */
$prev_time = (int) $_SESSION['prev_time']; /** grabbing the previous time from session */
$diff = $jsTime-$prev_time; /** getting the difference newly sent time and previous time by subtracting */
print("$jsTime - $prev_time = $diff"); /** printing the difference */
if($diff<3000){ /** checking if difference is less than 3 second if it is it means pc was not at sleep
*** you can manipulate and have for example 1 second = 1000ms */
socket_write($client,encode("You are active! your pc is awakend"));
$_SESSION['prev_time'] = $jsTime; /** saving newly sent time as previous time for future testing whcih will happen in two seconds in our case*/
}else { /** if it is more than 3 seconds it means that javascript setInterval function was paused and resumed after 3 seconds
** So it means that it was at sleep because when your PC is at sleep/suspended/hibernate mode setINterval gets pauesd */
socket_write($client,encode("You are not active! your pc is at sleep"));
$_SESSION['prev_time'] = $jsTime;
}
}else { /** if we have not saved the previous time in session save it */
$_SESSION['prev_time'] = $jsTime;
}
print_r($_SESSION);
/*
**** end of Main section for detectin sleep or not **
*/
}
}
} while (true);
// close sockets
socket_close($client);
socket_close($socket);
$client = null;
$flag_handshake = false;
function handshake($client, $headers, $socket) {
if (preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $headers, $match))
$version = $match[1];
else {
print("The client doesn't support WebSocket");
return false;
}
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) {
// 0x1 text frame (FIN + opcode)
$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;
}
UWAGA PRZECZYTAJ:
$new_time
zmienna znajduje się $jsTime
w kodzie
utwórz folder i po prostu skopiuj i wklej to w plikach uruchom gniazdo php za pomocą polecenia: php -f server_socket.php przejdź do localhost i przetestuj go otwórz konsolę, aby zobaczyć komunikaty z komunikatem „jesteś aktywny” lub „nie jesteś aktywny” (kiedy przychodzisz ze snu); Twoje wykonanie nastąpi, gdy użytkownik przejdzie ze snu, a nie kiedy jest w trybie uśpienia, ponieważ w tym momencie wszystko jest buforowane w pliku stronicowania (Windows) lub w zamianie (Linux)