PHP_SocketIO_Client icon indicating copy to clipboard operation
PHP_SocketIO_Client copied to clipboard

Sometimes works, sometimes doesn't

Open TyraelElDruin opened this issue 7 years ago • 8 comments

I'm hoping to use this on something I'm working on as a simple way to pass notifications to clients.

The issue I'm running into is that sometimes this works and sometimes it doesn't - there doesn't seem to be much rhyme or reason to it.

Sometimes it will instantly connect/disconnect without sending the message along - other times, it succeeds.

Have you tried using this to send multiple requests in succession?

TyraelElDruin avatar Feb 21 '18 00:02 TyraelElDruin

I just wanted to say that I can sort of workaround this for my purposes - I'd love to see a solution, but I can at least see that the php client has connected and fire an event to my clients that basically just says "update." It seems to work okay, but I'd like to hear if you have a solution.

Server:

io.on('connection', function(socket) {
  var ip = socket.request.headers['x-forwarded-for'] || socket.request.connection.remoteAddress;
  //localhost response
  if(ip == "::ffff:127.0.0.1") {
	io.emit('UpdateClients', "");
	console.log("Update Sent to Users");
  }

Client

  socket.on('UpdateClients', function(msg) {
      SomeTable.ajax.reload();
  });

TyraelElDruin avatar Feb 21 '18 01:02 TyraelElDruin

For anyone looking for a similar solution, I ended up going with this.

https://stackoverflow.com/a/49864533/1274820

I was looking for a really simple way to get PHP to send a socket.io message to clients.

This doesn't require any additional PHP libraries - it just uses sockets.

Instead of trying to connect to the websocket interface like so many other solutions, just connect to the node.js server and use .on('data') to receive the message.

Then, socket.io can forward it along to clients.

Detect a connection from your PHP server in Node.js like this:

//You might have something like this - just included to show object setup
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);

server.on("connection", function(s) {
    //If connection is from our server (localhost)
	if(s.remoteAddress; == "::ffff:127.0.0.1") {
		s.on('data', function(buf) {
			var js = JSON.parse(buf);
			io.emit(js.msg,js.data); //Send the msg to socket.io clients
		});
	}
});

Here's the incredibly simple php code - I wrapped it in a function - you may come up with something better.

Note that 8080 is the port to my Node.js server - you may want to change.

function sio_message($message, $data) {
	$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
	$result = socket_connect($socket, '127.0.0.1', 8080);
	if(!$result) {
		die('cannot connect '.socket_strerror(socket_last_error()).PHP_EOL);
	}
	$bytes = socket_write($socket, json_encode(Array("msg" => $message, "data" => $data)));
	socket_close($socket);
}

You can use it like this:

sio_message("chat message","Hello from PHP!");

You can also send arrays which are converted to json and passed along to clients.

sio_message("DataUpdate",Array("Data1" => "something", "Data2" => "something else"));

This is a useful way to "trust" that your clients are getting legitimate messages from the server.

You can also have PHP pass along database updates without having hundreds of clients query the database.

I wish I'd found this sooner - hope this helps! 😉

TyraelElDruin avatar Apr 17 '18 06:04 TyraelElDruin

Hi, Nice writeup.

The power of socket.io is in maintaining connections open, and updating data without performing requests. I've used this approach to solve a problem some time ago, but I ended up using redis as a fifo queue to pass data between php & nodejs. This is not optimal, having to install redis (I use docker-compose nowadays, so not much of a problem), but I think is a better solution for passing data from one side to another and vice-versa.

bitkill avatar Apr 17 '18 14:04 bitkill

Correct me if I'm wrong, but can't you just leave the socket open and send data as needed?

TyraelElDruin avatar Apr 27 '18 00:04 TyraelElDruin

I solved this problem this way: var io = require('socket.io')(app,{ pingInterval: 250, pingTimeout: 250, }); Just set up the server not to hang with every 2-5 request, as before. Tested on 10,000 requests per row - 100% of deliveries. I understand that this method is bad, but I did not find a better solution.

KitDevUA avatar Mar 02 '19 19:03 KitDevUA

I found better solution. The previous version overloads the server when large online. New solution:

socket.on('ACTION', function (data) { // on event from php-library
	io.to(data.room).emit('ACTION', data); // sending data
	socket.disconnect(true); // disable connection due to php-library bug
});

KitDevUA avatar Apr 03 '19 20:04 KitDevUA

Correct me if I'm wrong, but can't you just leave the socket open and send data as needed?

Sure, but php by definition creates an "instance" per request. This is great for REST api requests, but if you want to make a permanent solution, there are better alternatives. In my case I solved this by using redis to pass data to the node instance, and doing a proxy for the /socket.io/ location in nginx.

bitkill avatar Apr 05 '19 10:04 bitkill

I had the same problem as TyraelElDruin with this class. Sometimes my message arrived, sometimes it did not.

I solved it by placing a sleep(1) after the first fwrite().

EccoV avatar May 27 '21 18:05 EccoV