reactphp / socket

Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP.
https://reactphp.org/socket/
MIT License
1.21k stars 157 forks source link

Socket server need to restart on day start #259

Closed kailasb10 closed 3 years ago

kailasb10 commented 3 years ago

I've created the server in laravel command file & set in supervisor to run the socket server continuously to accept client msg

Laravel Command file code Server.php

$loop = React\EventLoop\Factory::create();
$IP = getHostByName(getHostName()); // this will get current server IP address // 192.168.0.50
$socket = new React\Socket\Server($IP.':8080', $loop);

$socket->on('connection', function (React\Socket\ConnectionInterface $connection) {
    $connection->on('data', function ($data) use ($connection) {
        // process data sent from client
    });
});
$loop->run();

Client.php

$loop = React\EventLoop\Factory::create();
$connector = new React\Socket\Connector($loop);

$connector->connect('192.168.0.50:8080')->then(function (React\Socket\ConnectionInterface $connection) use ($loop,$data) {
    $connection->write($data); // sent data to Server.php
});
$loop->run();

This is working fine but when I check on the next day it will be sent data from Client.php but not received at Server.php Then restart Supervisor of Server.php / php artisan server then it working fine for the whole day

WyriHaximus commented 3 years ago

You mentioned at https://github.com/reactphp/socket/issues/203#issuecomment-871327457 that his happens at midnight? What happens at midnight on that server and with your application? Aside from that this code looks fine, What is happening at // process data sent from client?

kailasb10 commented 3 years ago

I've found what exactly happen. I've set IP with port 192.168.0.50:8080 to communicate with the socket server. but when I've checked for the next day the IP is changed to 127.0.0.1:8080. Below is the solution to communicate with any IP address. Server.php

$loop = React\EventLoop\Factory::create();
$IP = getHostByName(getHostName()); // this will get current server IP address // 192.168.0.50
$IP = '0.0.0.0'; -> set this to I/O to any IP address
$socket = new React\Socket\Server($IP.':8080', $loop);

$socket->on('connection', function (React\Socket\ConnectionInterface $connection) {
    $connection->on('data', function ($data) use ($connection) {
        // process data sent from client
    });
});
$loop->run();

o sudo lsof -i -P -n | grep LISTEN -> run this cmd to check 8080 port with updated code, It's showing now *:8080

HLeithner commented 3 years ago

@kailasb10 you mean the IP of the server changes? or is the IP still the same but your socket server isn't listening to the unchanged IP?

kailasb10 commented 3 years ago

@kailasb10 you mean the IP of the server changes? or is the IP still the same but your socket server isn't listening to the unchanged IP?

I'm requesting 192.168.0.50:8080 but on the server, it's set to 127.0.0.1:8080 that's why it's not communicating may be getHostByName(getHostName()); this line gives the local IP. but after restart of supervisor, this line get getHostByName(getHostName()) server IP so it set back to again 192.168.0.50:8080

So I've changed in server.php file to create a connection with 0.0.0.0:8080 it's will start communicating with any IP address.

HLeithner commented 3 years ago

So you say (react)php looses the IP binding at some point in the process?

Switching to the wildcard IP 0.0.0.0 is a workaround but doesn't solve the actual problem.

Just to be on the same page.

  1. You start your ReactPHP Server
  2. It binds to 192.168.0.50 in port 8080
  3. it runs several hours without problem and sind bound to 192.168.0.50
  4. at some point in time it doesn't response anymore
  5. you check with lsof -i -P -n | grep LISTEN or netstat -lnp (should be the same result) and see that the PHP process with the same PID runs no on 127.0.0.1:8080
  6. you restart your ReactPHP Server and it works normally again bound to 192.168.0.50?
kailasb10 commented 3 years ago

So you say (react)php looses the IP binding at some point in the process?

Switching to the wildcard IP 0.0.0.0 is a workaround but doesn't solve the actual problem.

Just to be on the same page.

  1. You start your ReactPHP Server
  2. It binds to 192.168.0.50 in port 8080
  3. it runs several hours without problem and sind bound to 192.168.0.50
  4. at some point in time it doesn't response anymore
  5. you check with lsof -i -P -n | grep LISTEN or netstat -lnp (should be the same result) and see that the PHP process with the same PID runs no on 127.0.0.1:8080
  6. you restart your ReactPHP Server and it works normally again bound to 192.168.0.50?

yes

HLeithner commented 3 years ago

AFAIK that's not possible ;-)

Does your server loose the IP or network connect at some point? or maybe use DHCP?

WyriHaximus commented 3 years ago

Does your server lose the IP or network connection at some point? or maybe use DHCP?

That is a very good point! No clue how the socket server behaves what it expires, that would also depend on the network stack of the OS. But I wouldn't be surprised if it would fall back to the loopback interface and bind on 127.0.0.1 instead, it's unexpected from a consumer's POV. But maybe not so much from a network POV.

Also, if you lose that IP, an active connection might be dropped no matter how long. I kinda assumed you had a very good reason to go for a specific IP, but otherwise use 0.0.0.0 if you don't have a very good reason. Use a firewall to shield it off if you have to. Also look into using an on error handler on the client's side to reconnect when it disconnects: https://reactphp.org/socket/#connectioninterface

kailasb10 commented 3 years ago

Does your server lose the IP or network connection at some point? or maybe use DHCP?

That is a very good point! No clue how the socket server behaves what it expires, that would also depend on the network stack of the OS. But I wouldn't be surprised if it would fall back to the loopback interface and bind on 127.0.0.1 instead, it's unexpected from a consumer's POV. But maybe not so much from a network POV.

Also, if you lose that IP, an active connection might be dropped no matter how long. I kinda assumed you had a very good reason to go for a specific IP, but otherwise use 0.0.0.0 if you don't have a very good reason. Use a firewall to shield it off if you have to. Also look into using an on error handler on the client's side to reconnect when it disconnects: https://reactphp.org/socket/#connectioninterface

I've observed that this will happen when the server restart. I've checked in VM it creates an issue when the next day I've started & the same will happen when I've restarted my AWS server. I think when the server started the supervisor is also restarted that time somehow it didn't get the server IP then it points to the local IP image

I think when we get NULL IP address then it points to local IP (127.0.0.1) address

HLeithner commented 3 years ago

Thanks for you answer. It looks like that's a completely different scenario compared to my understanding of you description.

In this case I would expect ReactPHP (actually the underlying layers down to the kernel) behaves correctly. At point in time when your application starts you get the IP that exists in the system which is at least localhost. That means you application starts too early.

I don't know which supervisor you use, I can only suggest to change the start dependencies the way your application is started after the network stack is ready.

The good thing is that is not a ReactPHP issue 😅

kailasb10 commented 3 years ago

Thanks for you answer. It looks like that's a completely different scenario compared to my understanding of you description.

In this case I would expect ReactPHP (actually the underlying layers down to the kernel) behaves correctly. At point in time when your application starts you get the IP that exists in the system which is at least localhost. That means you application starts too early.

I don't know which supervisor you use, I can only suggest to change the start dependencies the way your application is started after the network stack is ready.

The good thing is that is not a ReactPHP issue 😅

yes. It's not ReactPHP issue :)