ghedipunk / PHP-Websockets

A Websockets server written in PHP.
BSD 3-Clause "New" or "Revised" License
917 stars 375 forks source link

How to disconnect user if internet connection is not available #116

Closed renznamoc21 closed 6 years ago

renznamoc21 commented 6 years ago

Hi.

How can i disconnect user if the internet connection change to none?

socket.close(); socket = null;

works manually and CLI logs Client disconnected

but when those codes called in offline event it doesn't logs any in CLI

Thank you

youssefali424 commented 6 years ago

did you trace the code? as there is a err handling for disconnected user so just add any variable to WebSocketUser that u want may be boolean so that you know he is disconnected , (by the way the server closes it as well thats if u trace the code u will find it)

renznamoc21 commented 6 years ago

I still cant trace the code called when the connection lost(sudden internet loss, changes of network connection)

ghedipunk commented 6 years ago

If a person is disconnected due to a network issue, the abstract function Websockets::closed will be run by Websockets::disconnect.

You are required to implement the closed() method. You are invited to override the disconnect() method if you need to know the particular reason why a given connection is closed.

And I am embarassed that I set it up this way originally.

renznamoc21 commented 6 years ago

It seems like the Websockets::disconnect does not called when a person is diconnected due to network issue, im running this using php 7 codeigniter framework and ubutu server, to recreate the network issue, i did disable my Ethernet adopter in network settings

youssefali424 commented 6 years ago

what was the error that you got? in the server

renznamoc21 commented 6 years ago

There is no any logs in server CLI nor any error at the time i disconnect/disabled my network

renznamoc21 commented 6 years ago

Here's the screen shot of server cli logs https://ibb.co/mzwHyU the the screen shot of browser in mobile after i turned off my wifi https://ibb.co/b6MjdU it says disconnected - status 3 but the server does not recognized it

please help me thank you

youssefali424 commented 6 years ago

https://ibb.co/c2oZDU so basically i just tried the raw server(i changed it alot for my needs before and i didnt work on it since two years ago) and it notices it as i said before and you can change the function to do whatever you want when disconnected

youssefali424 commented 6 years ago

i dont understand how you didnt notice the function its so direct they called it disconnect and you will see that the client get disconnected and deleted from users list in it as well(as i said before)

renznamoc21 commented 6 years ago

Yes disconnected works perfectly to me on close of browser/ browser's tab but while im connected then turn of my wifi disconnect function does not called i dont know why disconnect does not call when wifi is off, just like how disconnect call when browser/tab is closed

Xaraknid commented 6 years ago

I can explain what happens.

1- When you use "quit", you close normaly the websocket connection. 2- When you close the browser, you close abruptly the websocket connection. 3- When you unplug ethernet cable ( or wifi connection ), the websocket stay open.

It's the force of TCP if you plug back ( or reconnect wifi ) quick enought and have the same IP. The data will flow back on the last thing you receive.

So after some unresponse from client ( no ACK ) or the timeout on TCP occur the connection will be terminated.

You have 2 solutions if you want to wait for the OS to close the connections. 1- Set a timeout on TCP connection but be aware that you'll need to send data to the client to keepitalive 2- Use ping/pong on interval create a list of connection of all ping you send and remove the connection from the list if they pong. Then you can safely consider the one left on the list to be "ghost connection".

renznamoc21 commented 6 years ago

Thank you very much @Xaraknid , @ghedipunk , @youssefali424 for your help Question: It is safe to do that the client send ping to server every sec. to log the last time activity of user then in server checking all connected user last time activity if > 5sec user will be disconnected?

Xaraknid commented 6 years ago

All depend what you need.

You should use server side to send PING, all official current browser send Automaticaly the PONG.

Keep in consideration lag spike, loss packet, bandwidth, stress time, ect. Data is send/receive sequentially that mean if you send a huge message that take time your PING will be received after that.

So 5 sec you have a fair chance to disconnect a valid connection.

I suggest you let the OS deal mostly with that. Sure a Ping/Pong exchange is just 4 bytes but it add up quickly for something that should happens rarely. With 100 clients you ping every 5 secs you'll end up with 288 Kbytes/hour. Also the CPU usage to fill and unfill the list.

You should check every X (higher than TIMEOUT) minutes that will not stress unecessary the server. Also make sure to remove from the list the disconnected that happens between every check.

renznamoc21 commented 6 years ago

Any idea how to do this server side ping and how server manage the pong of client ?

youssefali424 commented 6 years ago

the easy way send a specific message(num or word.....etc) then the client should replay if the ack didnt come then he is disconnected for sure you have to implement it in client and server side(make a timer to know idle users like if there is no traffic or data sent to server send the ack )

youssefali424 commented 6 years ago

or you can depend on the browser for the pong like check the browser response as Xaraknid said but you need to know how the browser respond

renznamoc21 commented 6 years ago

Thank you very much guys

Xaraknid commented 6 years ago

My first advice "using ping-pong built-in" was not that great. First that mean you'll need to do code into websocket, and second I forget about microsoft and their mindset of doing thing their way ( IE explorer send PONG every 30 seconds ).

You should follow @youssefali424 advice "make your own ping-pong system".

As for how to do it I can think of 2 ways :

1- add a variable "ALIVE" as boolean inside users. Not my prefered one as you'll have (O)n * 2. First loop as you send your ping to all users and modify ACTIVE equal FALSE -For each Pong you set ACTIVE equal TRUE Second loop you scan all users to check if they are ACTIVE and disconnect them if not.

2- You used an array "Ghosts" with only the userid in it as value. You'll have a (O)n + (O)n - those who respond in time (should be empty most of the time ) First loop as you send your ping to all users and you add the userid into Ghosts array -For each Pong you remove userid from Ghosts Second loop you scan Ghosts array and what left in it are your inactive user.

EDIT : The second loop should come first into your function. In case 1 the default value when new connection is TRUE. In case 2 do not forget to remove from Ghosts array when someone disconnect from the server normally.