Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Websockets as EventSource is this possible? #94

Open
petrospap opened this issue Feb 26, 2017 · 9 comments
Open

Websockets as EventSource is this possible? #94

petrospap opened this issue Feb 26, 2017 · 9 comments

Comments

@petrospap
Copy link

After many attempts finally I decided that I use PHP-Websockets for a small chat application into my website.

Now I have an idea but I'm not sure if theoretically can be accomplished!!!

So, let’s say that I want to display some data in real-time (NOT CHAT)

If we have 1000 users in to website mean that we have 1000 connections in server, and if connect other 1000 users then is sure that server are going to crash!

My idea is to make a bot to act as user/client and to make a handshake with correct Sec-WebSocket-Key by sending headers with curl.

In this way, we need a single connection to display anything to all users, rather than connect all users to the server!

Theoretically speaking, can this idea be accomplished?

@Xaraknid
Copy link
Collaborator

Xaraknid commented Feb 27, 2017

berkeley socket aka select socket have a limitation of 1024 concurrent connections if you need more than that you'll have to use event poll socket .

Not sure what you asked? the server by itself have the power to broadcast any data to every client connected to it.

@ghedipunk
Copy link
Owner

I'm really not sure what's being asked either.

If you have over 1000 users connected to some open socket, so that they can receive updated data in real time, they're going to need each connect to something, whether they're connecting to your main application server or if they're connecting to some secondary server that is receiving these notifications and passing them on to the users.

Some alternatives:

Realize that not all near-real-time data has to travel through a WebSockets connection. You could have an AJAX endpoint on your server that gets polled by your users periodically. Is this information that needs to get to your users within milliseconds, or can they wait a second or two? Is the updated data the same for every single user, so that they can have a reverse proxy (Varnish-Cache or similar) serve the data without affecting your application data, and when data is updated, you simply need to invalidate the cache?

If you need WebSockets to handle over 1000 concurrent connections, I strongly recommend using Xaraknid's fork, where he uses libev. It can handle several thousands of open connections; your bottleneck becomes the physical hardware of your network, rather than the server itself generating and sending messages.

If you find yourself passing the limits of your network hardware, the only course left, regardless of whether you're using this version of WebSockets that uses Berkeley Sockets, using libev, or you're using any other transport such as AJAX, is to design a replication and load balancing system. This is where you'd build a "bot" that your users would connect to, that would mediate requests between users and your application server. And, this is also the hardest option to do right, because you either lose consistency or responsiveness. Either the data that you're sending to your users has a chance to not reflect the current state of the system, because not all servers can communicate instantaneously with each other (blame the speed of light), or the system will have to wait for every server to agree on the current state after every update, locking the entire system every time any data changes. (If you can find a way to have both consistency and responsiveness in a distributed system, every major tech firm will be bidding for your software.)

@petrospap
Copy link
Author

OK I try to rephrase my question

How to display real time data to all users WITHOUT to connect all users?

My idea is to create a bot and he try to make handshake with some page (this page is also a bot?)

If you have handshake between bot and page, this bot can echo to page real time data, and users can see the data in page?

I don’t know if this theory can work

here is how to try to make a bot to connect (unsuccessful so far )

bot.php

<?php
class echoBot{
	
function bot($host='',$headers=''){

	$key=base64_encode(uniqid('u'));
	$header = "GET /1 HTTP/1.1\r\n"
		."Host: $host\r\n"
		."pragma: no-cache\r\n"
		."Upgrade: websocket\r\n"
		."Connection: Upgrade\r\n"
		."Sec-WebSocket-Key: $key\r\n"
		."Sec-WebSocket-Extensions: permessage-deflate\r\n"
		."Sec-WebSocket-Version: 13\r\n";

	# Add more extra headers ?
	if(!empty($headers)) foreach($headers as $h) $header.=$h."\r\n";  

	# Add end of header marker
	$header.="\r\n";
	$socket=fsockopen($host); 
	if(!$socket){
		echo "Unable to connect to websocket server";
	//    return false;
	}else{
		echo'fsockopen ok<br>';
	}

	#Set timeouts
	// stream_set_timeout($socket,$timeout=10);

	# Request upgrade to websocket 
	$rc = fwrite($socket,$header);
	if(!$rc){
		echo "Unable to send upgrade header to websocket server";
	//    return false;
	}else{
		echo 'Headers send<br>';
		echo '<pre>';
		print_r($header);
		echo '</pre>';
	}
  
	# Read response into an assotiative array of headers. Fails if upgrade fails.
	$reaponse_header=fread($socket, 1024);

	# status code 101 indicates that the WebSocket handshake has completed.
	if(!strpos($reaponse_header," 101 ") || !strpos($reaponse_header,'Sec-WebSocket-Accept: ')){
		echo "Server did not accept to upgrade connection to websocket.";
		//return false;
	}else{
		echo 'We connect to server<br>';
		echo '<pre>';
		print_r($reaponse_header);
		echo '</pre>';
	}

	//return $socket;
  
	//	while (!feof($socket)) {
	//		echo 'Conection is closed!!';
	//	exit;
	//	}
	//$status = stream_get_meta_data($socket);
	//print_r($status);
}

}

$newecho = new echoBot();
try {
  $newecho->bot('127.0.0.1:9000');
}
catch (Exception $e) {
  $newecho->stdout($e->getMessage());
}

Running this page the results from server is

Please close this command only for Shutdown
server websocket is starting ...
1--> Server started
Listening on: 0.0.0.0:9000
Master socket: Resource id # 8
1--> Client connected. Resource id # 9
<<-----GET --> 1 IP --> 2130706433 ID from db -->1 totalusers= 1
<<-----@socketID = (Resource id # 9) -- GET= 1
1--> Client disconnected1. Resource id # 9
1--> Closed socket: Resource id # 9
2--> Client disconnected2. TCP connection lost: Resource id # 9

Client disconnected1 is from function disconnect
Client disconnected2 is from $numBytes == 0

some idea how to overtake those disconnects?

@petrospap
Copy link
Author

forgot the response from bot.php

fsockopen ok
Headers send

GET /1 HTTP/1.1
Host: 127.0.0.1:9000
pragma: no-cache
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dTU4YjU3OTdmZTdjZmY=
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Version: 13

We connect to server

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: O+uUfaGHGpAgFIyJkIvYzX5sENg=

Conection is closed!!

@ghedipunk
Copy link
Owner

Where's your event loop in the bot?

@Xaraknid
Copy link
Collaborator

Xaraknid commented Mar 1, 2017

websocket is exactly for pushing data realtime. Http by default didn't work that way, for user to see new data on the same page have to refresh it aka "F5". The browser send a "get" request and the http server will send data/page as it was on the exact time he process the request.

With a websocket server THE server will ack as the bot you wish to have.

Complement of information : sure you can use bot if you really need an external way but you still need to implement inside the websocket server broadcasting ability.

As ghedipunk said you need a loop to keep connection active.

@petrospap
Copy link
Author

I have a idea how to do this but need to learn more, so first i start to make the chat application and parallel I see how I can implement the bot.

@petrospap
Copy link
Author

Hello I need some help here

How you said I need an event loop but I don’t know how to read the messages!

With this simple script above, If i try with $socket=pfsockopen($host) I have persistent connection with server, i.e printHeaders seems correct and I have Resource ID in server

Can you PLEASE give me any idea how to read any message that sends the server and to try to echo from the above bot!!

Any idea???

@adminy
Copy link

adminy commented Sep 25, 2018

What he wants is convert a socket connection to a web page 😅 so that the server serves static pages but dynamic relative to what the socket server gives.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants