Run a file 24x7 on server using PORT - php

I am stuck with this problem. I am using a server ( I have full excess rights and can do anything ). On this, I want to run a file which will connect to a port and receive data from devices. These devices will send data using TCP.
Server file should run continuously, 24x7, without any break. But it is not happening. To understand deeper I am pasting the code.
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
$result = socket_listen($socket) or die("Could not set up socket listener\n");
while(true) {
if ($spawn = socket_accept($socket)) {
if ($input = socket_read($spawn, 1024)) {
// MY REST OF THE CODE HERE
}
socket_close($spawn);
unset($spawn);
}
}
In line number 5, server will accept the connection and next loop will be executed. It goes well if devices are sending data continuously. It will wait for device and once receive data, it will proceed further. But after some hours, server file stops responding. Port is consumed but server does not work on data. I made a client file to test whether port is working or not. Client file successfully connected with server.
What should I do to run this file continuously 24x7 without error.
One more thing I want to ask is, what if for some time device stops sending data ? Will it affect line 5 ? and this will lead to file hang ?

Related

php - how to create a socket server in my webhost

I've a webhost and I want to create a socket connection with my application .
I've this code :
<?php
$host = "127.0.0.1";
$port = 25003;
// don't timeout!
set_time_limit(0);
if (!extension_loaded('sockets')) {
die('The sockets extension is not loaded.');
}
// 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, 3) or die("Could not set up socket listener\n");
// accept incoming connections
// spawn another socket to handle communication
$spawn = socket_accept($socket) or die("Could not accept incoming connection\n");
// read client input
$input = socket_read($spawn, 1024) or die("Could not read input\n");
// clean up input string
$input = trim($input);
echo "Client Message : " . $input;
// reverse client input and send back
$output = strrev($input) . "\n";
socket_write($spawn, $output, strlen($output)) or die("Could not write output\n");
// close sockets
socket_close($spawn);
socket_close($socket);
?>
when I run the page , it returns "Could not create socket"
I'm running the code on a share web service
what is the problem ? How can I fix it ?
I tried your code on my machine with XAMPP installed and is working, it actually does open that port, I tested with telnet through putty. Answering to your questions I think like #Jon Stirling said your hosting does not allow you to create a socket. That's why hosting companies sell web hostings packages and virtual private servers, if you want to bind a port you should look for a VPS.
I am sure you have solved this and moved jobs since you posted it but as someone who has just gone through this I would like to direct everyone who lands here to this page:
https://www.php.net/manual/en/function.socket-select.php
I was looking for a way to have a socket server that does not chew up CPU cycles and only does something when there is something to do. That solution blocks while it is waiting for connections to do something then it processes them.
Pay special attention to the comments about setting $tv_sec to null as this is the "Make Work" flag that prevents chewing up the CPU.
This allows one to create a socket server in PHP that does not chew up CPU and also processes multiple connections.
The only missing piece of the puzzle is disconnecting clients that do not disconnect themselves.
Unless there is a connection timeout that can be set I think the solution is to set $tv_sec to some suitable value, like 2 seconds, and then track the time a connection has been connected then disconnect it if it breaches some time. The downside to this is it will use CPU but if you unblock every 2 seconds then you can use that to process timeouts etc. Otherwise, you have to rely on clients disconnecting. That may not be an issue for you but in my particular usecase it is.

Socket connection on same machine, PHP to C++ and back

I had to implement a communication between an application written in c++ and a web server scripted with PHP.
The basic idea was to create a socket with the c++ application, binding it and listen for the PHP connection to it.
The PHP would then send a message over TCP asking for data and the c++ would send back the answer. Single header request, single string(JSON) answer.
So far, so good.
This is the code I used for the PHP side:
<?php
error_reporting(E_ALL);
$service_port = 8080;
$address = 'localhost';
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
}
echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result === false) {
echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
}
$in = "request1";
$out = '';
socket_write($socket, $in, strlen($in));
$buf = 'This is my buffer.';
if (false !== ($bytes = socket_recv($socket, $buf, 2048, MSG_WAITALL))) {
echo "Read $bytes bytes from socket_recv(). Closing socket...";
} else {
echo "socket_recv() failed; reason: " . socket_strerror(socket_last_error($socket)) . "\n";
}
socket_close($socket);
echo $buf . "\n";
//elaborate the $buf
?>
Now I would like to implement also an auto-update of the data, with the c++ (server side) sending data and the PHP side(client side) to collect them.
The data update should be done every minute.
Sadly I don't have much experience with web developing, so I'm kindly asking some advices on that.
The easiest thing I could do was looping the PHP code untill a known message got received. The problem I faced is that I don't get data untill the loop is over and the PHP script ends.
To overcome the problem I tried to set PHP side the socket to be non-blocking
replacing in the socket_recv the option MSG_WAITALL with MSG_DONTWAIT but nothing changed. Then I tried to break out of the PHP script, but it can't be done since I need to cycle it to get the data every second.
Plus I get another problem, during the loop cycles, the apache server the PHP is running on is getting a 503 error, Server Unavailable.
I don't know why it happens, maybe the received message buffer is full, or the script takes too many resources.
Due to my lack of experience I can't understand why.
I know there are good libraries to perform what I need but I'm working on an embedded machine so I'm limited to work with basic libraries.
How can I achieve the PHP on the Apache server to get timed data from the c++ application ? What am I overlooking ?
Thanks a lot in advance for your help.
Edit: Deleted rhetorical question.
Using php to obtain data from another process via tcp/ip will require a bit more effort compared to sending data from a php script executed via apache to another process using tcp/ip sockets.
Your php script will need to be started outside of apache and will require an infinite loop that continuously listens to the given port to read input data. The following post outlines what I believe you are after.
EDIT
In order to display the results on the web page you could use an in memory data store such as Redis. The php server application would update a data structure in redis, then the webpage onload could pull the latest value from redis and display it on screen, however this would require a page refresh.
If you require that the data be refreshed immediately once received without server postback, this will require some javascript. When a user loads the page you would initialize a websocket connection with a websocket server (people generally use node.js and socket.io for implementing this but you can code a websocket server in anything that supports the technology). The websocket server would be subscribed to a redis channel that when updated would send the new values to all connected clients. I suppose this could be done without redis as well depending on what your requirements are. The program for the websocket server could also be the server that accepts the information from your c++ program using a separate thread. When data comes in from the c++ program you could then send it directly to the clients connected via websocket.
Don't reinvent the wheel. Use a websockets. It's designed to do this async communication and you can send JSON over it just fine.
There are libraries for C++ and PHP, meaning this should be pretty easy.

Creating PHP relay using sockets between multiple clients and servers

I've got a Python server which multiple clients connect to using sockets. At the moment one server isn't able to cope with the load so I'm looking at ways to split the clients up according to some criteria such as their username.
The intention is to put clients with usernames starting with A-G on server 1, H-P on server 2 and P-Z on server 3.
What I'm trying to do is to write a process that will listen for connections on port 45000 and will then forward those on to the appropriate server on 45001, 45002 and 45003.
At the moment, when a client connects to the original server they connect via a TCP port e.g. 45000. The server checks that they are authorised and responds on a random port with a handshake e.g. 59117, 60647 or 61573.
The response port is not specified when the client first connects so my question is, when is the value determined and how does the client know to listen on that port for the reply ?
So far I've written a PHP process which takes the data from the clients and forwards it to the appropriate server but I can't work out which port to listen on for the response back from the server. Is there some way that PHP sockets can negotiate the response port so that it can be stored in a variable in my script ?
Here's my basic connection code in PHP. I have no knowledge of Python so this is going to have to be done in PHP:
// Define remote Server
$socket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// Open socket on remote server to send $buf data to
socket_connect($socket, 'X.X.X.X', 40149);
echo ("Forwarding data ($buf) to $socket ....\r\n");
$bytesWritten=socket_write($socket, $buf, strlen($buf));
echo ("Wrote: $bytesWritten bytes\r\n");
// Now listen for response but this will be on another socket
// How do we know what this is ?
if (false === ($response = socket_read($socket, 16384))) {
echo ("Response: $response\r\n");
}
This is way out of my comfort zone so I may have this completely wrong but an afternoon spent Googling has turned up any answers yet.

PHP socket server doesn't react to client connections on my shared hosting account

On my shared hosting account in the public_html directory I have a php file that contains code for creating a socket server.
<?php
set_time_limit(0);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$ret = socket_bind($sock, 'localhost', 80);
$ret = socket_listen($sock);
$msgsock = socket_accept($sock);
socket_write($msgsock, " hello");
?>
When I open that php file with a browser or run it as a command, the socket server waits for a client connection and after that the code should send "hello" to the client and finish executing. I know that the actual socket server must have a loop in it, so that it can work properly, but this code is just for testing. Also in the public_html I have a php file which is a client,
<?php
set_time_limit(0);
$mysocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$result = socket_connect($mysocket, 'localhost', 80);
if ($result === false) {
echo "error";
} else {
echo "successfully connected";
}
$input = socket_read($mysocket,1024);
echo $input;
?>
and when I open it in a browser, it successfully connects to localhost on port 80 even if the php server file is not running. But when the php server file is running and waiting for a client connection, it continues to run even after the client file successfully connects to localhost, although without receiving "hello". When I try the same thing on my computer using apache server and run those files from another computer through the Internet, it works, that is the server file accepts the client, sends "hello" and finishes executing. So, what could be the reason why the php socket server doesn't react to client connections on my shared hosting account?
Thanks in advance
Use a port other then 80 to listen on. Its probably failing to create the server because the webserver is running on port 80.

socket_accept seems to hang on the first connection

I'm trying to make a simple listener on port 8195. When I try the following code block in PHP CLI conditions, it only shows 'Test' once, then hangs. If I delete the file 'votifier.run', the file designed to be the on/off switch, it still continues to hang. It never shows 'Client connected'.
Furthermore, if I try to connect to the host via Telnet on port 8195 while the script is running, I simply get a connection failed message. It's like it's looking for one connection and just not giving up.
// Set the IP and port to listen to
$address = 'localhost';
$port = 8195;
// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port);
// Start listening for connections
socket_listen($sock);
// Loop continuously
while ( file_exists('votifier.run') ) {
echo 'Test';
$client = socket_accept($sock);
if( $client ) {
echo 'Client connected';
// Don't hang on slow connections
socket_set_timeout($client, 5);
// Send them our version
socket_write("VOTIFIER MCWEBLINK\n");
// Read the 256 byte block
$block = socket_read($client, 256);
...
The answer:
socket_accept() will usually hang until a connection is made. If a connection attempt was made, the script would continue, but because the socket was being created on localhost, it would only accept connections to it from localhost.
The fix is to use your external IP rather than 'localhost' or '127.0.0.1'. Then you can Telnet to it.
I'm just guessing here, but could it be that the address you are trying to bind to should not be a hostname?
If the socket is of the AF_INET family, the address is an IP in dotted-quad notation (e.g. 127.0.0.1).
EDIT
Ok, I've taken your script and tried to reproduce your error but couldn't. There are a couple of flaws in it but none that would cause a telnet client's connection attempt to fail.
Since none of the aforementioned applies, let's go thru the checklist one by one:
sockets module loaded/compiled
localhost does resolve to 127.0.0.1
the port isn't taken by any other application running
there's no rule of any sort of firewall that would prevent communication between the telnet client and your server
the machine which you connect from is allowed to connect to the server host (try the same host if it isn't)
the file that's being checked in the while-loop does exist
you are sure that there isn't another fatal error within your script that would prevent the snippet you posted from running
These are all the possible error sources I can think of, atm. Try fixing up the minor flaws first, then go thru the checklist.
if( $client ) {
echo 'Client connected';
// Don't hang on slow connections
socket_set_option(
$client,
SOL_SOCKET,
SO_RCVTIMEO | SO_SNDTIMEO,
array('sec' => 5, 'usec' => 0)
);
// Send them our version
socket_write($client, "VOTIFIER MCWEBLINK\n");
^^^^^^^
// Read the 256 byte block
$block = socket_read($client, 256);
You should be using threads. If the client never sends anything your code will block in the read() method. Each accepted socket should be completely handled in a new thread.
You may want to check this:
PHP Votifier example for Minecraft Topsites
It explains how the code works, it's the basic function that makes the encryption, fills up the 256 blank spaces and sends the packet too. You can work a little with it as you may want to improve it.
You can see a live demo of the running php for the plugin here: http://topg.org/test_votifier

Categories