PHP Socket Disconnecting Randomly - php

I'm using a PHP Socket to listen on port 6000 for incoming connections and its working perfectly 99% percent of the time but 1% of the time the client is getting a connection error when sending a request to the server. I created a different script to ping the socket on port 6000 every second in an infinite loop and write the result to a log file so I can see if its breaking, and out of 78,000 Successful pings, 23 Failed.
There must be some small logic error with my code which is causing this. If anyone has any ideas its much appreciated.
Socket:
if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0)))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg \n");
}
echo "Socket created \n";
// Bind the source address
if( !socket_bind($sock, "0.0.0.0" , 6000) )
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not bind socket : [$errorcode] $errormsg \n");
}
echo "Socket bind OK \n";
if(!socket_listen ($sock , 10))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not listen on socket : [$errorcode] $errormsg \n");
}
echo "Socket listen OK \n";
echo "Waiting for incoming connections... \n";
//start loop to listen for incoming connections
while (true)
{
//Accept incoming connection - This is a blocking call
$client = socket_accept($sock);
//read data from the incoming socket
$input = "";
$input = socket_read($client, 10000000);
if ($input != "")
{
// do my logic here with $input
}
}
socket_close($sock);
EDIT: No, I'm not using CMD to ping. This is my PHP script which is doing the pinging:
<?php
$host = '0.0.0.0';
$port = 6000;
$waitTimeoutInSeconds = 1;
while(true)
{
if($fp = fsockopen($host,$port,$errCode,$errStr,$waitTimeoutInSeconds))
{
$file = 'log.txt';
$current = file_get_contents($file);
$today = date("Y-m-d_H:i:s");
$current .= $today . " - SUCCESS\n";
file_put_contents($file, $current);
}
else
{
$file = 'log.txt';
$current = file_get_contents($file);
$today = date("Y-m-d_H:i:s");
$current .= $today . " - FAILED\n";
file_put_contents($file, $current);
}
fclose($fp);
sleep(1);
}
?>
For an actual transaction, the client is only connected for a split second while it sends through an xml request in raw text, then it does some logic which takes less than a second. Since its failing on the ping test though, that means my listener is breaking for a second for one reason or another does it not?

I'm not sure if I understand correctly.
You say about 0,03% of your pings failed. Is this your problem? If these are real pings (ping.exe from cmd.exe) then it has nothing to do with your logic. It's the network. (Is the host on WIFI?)
If you are convinced it's your logic:
If someone connects, how long is he connected? And what happens to new requests while connected to the previous client? I think you may find your answer here.
Also try to do a test with a client that continuously connects and sends dummy data, in stead of pinging. And log what responses the client is receiving.

Related

PHP Socket Programming. Need to support 300 multiple connection at same instance

I have created a PHP socket on my server on port "11011". Which is working properly for multiple connections. But it only supports around 20-60 parallel connection. That is also not constant. I I want my server to at least support 300 parallel connection. Please Help.
Here is my code at server side :
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
set_time_limit (0);
date_default_timezone_set('UTC');
$address = "0.0.0.0";
$port = 11011;
$max_clients = 1024;
if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0)))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
// echo "Couldn't create socket: [$errorcode] $errormsg \n";
die("Couldn't create socket: [$errorcode] $errormsg \n");
}
echo "\n\n".date('Y-m-d H:i:s')." Socket created\n";
if( !socket_bind($sock, $address , $port) ){
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not bind socket : [$errorcode] $errormsg \n");
}
echo "\n\n".date('Y-m-d H:i:s')." Socket bind OK\n";
if(!socket_listen ($sock , 10))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not listen on socket : [$errorcode] $errormsg \n");
}
echo "\n\n".date('Y-m-d H:i:s')." Socket listen OK \n";
echo "\n\n".date('Y-m-d H:i:s')." Waiting for incoming connections... \n";
//array of client sockets
$client_socks = array();
//array of sockets to read
$read = array();
while (true)
{
$read = array();
//first socket is the master socket
$read[0] = $sock;
//now add the existing client sockets
for ($i = 0; $i < $max_clients; $i++)
{
if(!empty($client_socks[$i]))
{
$read[$i+1] = $client_socks[$i];
}
}
//now call select - blocking call
if(socket_select($read , $write , $except , null) === false)
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not listen on socket : [$errorcode] $errormsg \n");
}
//if ready contains the master socket, then a new connection has come in
if (in_array($sock, $read))
{
for ($i = 0; $i < $max_clients; $i++){
if (empty($client_socks[$i])) {
$client_socks[$i] = socket_accept($sock);
if(socket_getpeername($client_socks[$i], $address, $port))
{
echo "\n".date('Y-m-d H:i:s')." Client $address : $port is now connected to us. \n";
// echo date('Y-m-d H:i:s')." Client $address : $port is now connected to us. \n";
// $clientTimestamp[$i] = time();
}
break;
}
}
}
//check each client if they send any data
for ($i = 0; $i < $max_clients; $i++)
{
if (!empty($client_socks[$i]) && in_array($client_socks[$i] , $read))
{
$input = socket_read($client_socks[$i], 2048);
echo "\n\n".date('Y-m-d H:i:s')." INPUT : $input\n";
if($input != null){
$output = "\x06";
socket_write($client_socks[$i] , $output);
}else{
socket_close($client_socks[$i]);
unset($client_socks[$i]);
}
}
}
}
?>
Here is my code at client side, which I hit for multiple times at same time to connect with server and check the load. However, it only opens random 60-70 connections when I run 100 such scripts.
If I run 50 such scripts, it works taking all 50 connections. But sometimes only take 25-30 connections.
Code at client side.
<?php
$host = SERVER_IP;
$port = 11011;
callSocket("\x05",true,false);//ENQ
$message = "\x02 Hello How are you\x03";
callSocket($message,false,false);
callSocket("\x04",false,true);//EOT
function callSocket($message,$connect,$disconnect){
global $host,$port,$socket;
// create socket
if($connect){
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
// connect to server
$result = socket_connect($socket, $host, $port) or die("Could not connect to server\n");
}
// send string to server
socket_write($socket, $message, strlen($message)) or die("Could not send data to server\n");
// get server response
$result = socket_read ($socket, 1024) or die("Could not read server response\n");
echo "Reply From Server :".$result;
// close socket
if(empty($result) || $disconnect){
echo "\n--Close ASTM connection--\n";
socket_close($socket);
}
}
?>
Here are the server setting:
Red Hat Enterprise Linux Server release 6.8 (Santiago)
PHP version 5.6
soft nofile 300000
hard nofile 300000
sysctl net.core.somaxconn=1024
sysctl net.core.netdev_max_backlog=2000
sysctl net.ipv4.tcp_max_syn_backlog=2048
ifconfig eth0 txqueuelen 5000
echo "/sbin/ifconfig eth0 txqueuelen 5000" >> /etc/rc.local
Here are the server setting on client side:
sysctl net.ipv4.ip_local_port_range="15000 61000"
sysctl net.ipv4.tcp_fin_timeout=30
sysctl net.ipv4.tcp_tw_recycle=1
sysctl net.ipv4.tcp_tw_reuse=1

php socket server works only on localhost but not live server

I have hosting domain godaddy and i enabled socket module, but dose not work
this code works only in localhost when i upload it in server it does not work.
code server.php
<?php
// set some variables
$host = '150.113.178.20';
$port = 5000;
if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0)))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg \n");
}
echo "Socket created \n";
// Bind the source address
if( !socket_bind($sock, $host , $port) )
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not bind socket : [$errorcode] $errormsg \n");
}
echo "Socket bind OK \n";
if(!socket_listen ($sock , 10))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not listen on socket : [$errorcode] $errormsg \n");
}
echo "Socket listen OK \n";
echo "Waiting for incoming connections... \n";
//start loop to listen for incoming connections
while (true)
{
//Accept incoming connection - This is a blocking call
$client = socket_accept($sock);
//display information about the client who is connected
if(socket_getpeername($client , $address , $port))
{
echo "Client $address : $port is now connected to us. \n";
}
//read data from the incoming socket
$input = socket_read($client, 1024000);
$response = "OK .. $input";
// Display output back to client
socket_write($client, $response);
}
when i execute server.php script in ssh no problem
but when i write from CMD :
Error log file
After some research i found that The code is correct
Godaddy does not open custom ports.
The code does not work because have a different security policy localhost than GoDaddy (or other hosting website).

Send data from web server to perl socket listener

I try to send data from php web script to local perl socket listener.
Here is perl server code:
#!/usr/bin/perl
use IO::Socket::INET;
use strict;
$| = 1;
my $web = new IO::Socket::INET (
LocalHost => '127.0.0.1',
LocalPort => '9001',
Proto => 'tcp',
Listen => 5,
Reuse => 1
) or die "ERROR in Socket Creation : $!\n";
while ($web->accept()) {
my $web_address = $web->peerhost();
my $web_port = $web->peerport();
print "Accepted New Web Client Connection From : $web_address, $web_port\n";
my $data = <$web>;
chomp ($data);
print "Data from web: $data\n";
}
And here is php code:
if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0)))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg \n");
}
echo "Socket created \n";
if(!socket_connect($sock , '127.0.0.1' , 9001))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not connect: [$errorcode] $errormsg \n");
}
echo "Connection established \n";
$message = "GET / HTTP/1.1\r\n\r\n";
if( !socket_send ($sock , $message , strlen($message) , 0))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not send data: [$errorcode] $errormsg \n");
}
echo "Message send successfully \n";
Here is output of perl script:
Accepted New Web Client Connection From : ,
Data from web:
And here is output of php script:
Socket created
Connection established
Message send successfully
So, why it actually don't send the data?
The $web->accept() only creates and returns an object, which can be used to read the handle (for the socket). You are attempting to read with $web itself, which it cannot do. In other words, <$web> does not read from the socket. The PHP client has sent its message which is sitting in the buffer waiting to be read.
Further, as the PHP client prints it is filling up the buffer, since nothing is emptying it (reading) on the other end. If it prints enough at one point the buffer will get full and the next print will hang, just waiting. This is a common source of errors, when the buffer is not being read from orderly.
Your code needs small changes
if ( my $listen = $web->accept() ) {
my ($buff, $recd);
while (defined($buff = <$listen> ) {
chomp($recd = $buff);
# process the line in $recd
}
} else { warn "Error with the socket -- $!"; }
The while around $buff = <$listen> is needed to read more than one line as they are sent. For multiple connections that you allow all of this should be in a while loop, which you have. In a nutshell, for the one-line-message in your posted example
my $listen = $web->accept();
my $recd = <$listen>;
chomp($recd);
print "$recd\n";
This is as far as Perl code goes. I don't know how PHP routines work (they seem to be OK to me).
While IO::Socket provides basic information, there is a lot more scattered around Perl documentation. For example, there is a server example using IO::Socket in
Perl IPC, by the very end of that page.
Please add use warnings; at the beginning. It is actually extremely useful. I suspect that it would have warned you of this.

Sending json data through PHP sockets in Windows 7 command line windows

I checked
php sockets read json array from java server
Sending configuration data to websocket
and spent all day on finding the solution for the following problem.
I have Client.php
<?php
if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0)))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg \n");
}
echo "Socket created \n";
//Connect socket to remote server
if(!socket_connect($sock , '127.0.0.1', 23))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not connect: [$errorcode] $errormsg \n");
}
echo "Connection established \n";
$data = file_get_contents ("C:\Users\(myUsername here)\Desktop\sockets\Test.txt");
$json = json_decode($data, true);
echo $data . " this is data from file\n";
echo $json . " this is decoded version\n";
echo json_encode($data) . " this is encoded version\n";
$jsonSer = serialize($json);
//socket_write($sock, count($json). "\n\r");
socket_write($sock, $jsonSer);
echo $jsonSer . " this is serialized version\n";
echo unserialize($jsonSer) . " this is unserialized message\n";
//Send the message to the server
//$sock , $message , strlen($message) , 0
//JSON.stringify(data)
if( ! socket_send($sock, $jsonSer, 1024, 0))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not send data: [$errorcode] $errormsg \n\r");
}
echo "Message send successfully \n";
?>
And Server.php
<?php
// we create the socket (domain, type, protocol)
$socket = socket_create(AF_INET, SOCK_STREAM, 0);
// AF_UNIX
// if false we pass error code to strerror to get a textual explanation of the error
// and exit execution of the code
if (!$socket) {
echo "Couldn't create socket";
exit(socket_strerror(socket_last_error()));
}
echo "Socket created.\n";
//$address = '127.0.0.1';
//$port = '23';
// we bind the name given in address to the socket
$socket_bound = socket_bind ($socket , '127.0.0.1', 23);
if (!$socket_bound) {
echo "Couldn't bind socket";
exit(socket_strerror(socket_last_error()));
}
echo "Socket bound.\n";
// we tell the socket to listen for incoming connections on socket and keep them in
// backlog (e.g. 25)
$backlog = 25;
$socket_is_listening = socket_listen($socket, $backlog);
if (!$socket_is_listening) {
echo "Socket is not listening";
exit(socket_strerror(socket_last_error()));
}
echo "Socket is listening...\n";
// we set socket to be non-blocking in order to fork connections
socket_set_nonblock($socket);
echo "Waiting for connections...\n";
$server_is_listening = true;
while($server_is_listening) {
// Accept incoming connection
$connection = socket_accept($socket);
if (!$connection){
// we check every 100ms for new connections
usleep(100);
}elseif($connection>0){
// fork connections
// update connections progress and tell the user
// parse json to php object or array (2nd para = 1)
//$database_data_php = json_decode($database_data_json,0);
// accept incoming connection
/* //display information about the client who is connected
if(socket_getpeername($client , $address , $port))
{
echo "Client $address : $port is now connected to us.";
}*/
$response = "Amazing, server responded";
echo "Yay !!! We have a connection\n";
if(socket_getpeername($connection , $address , $port))
{
echo "Client $address : $port is now connected to us. \n";
echo "Connection is: $connection\n";
}
//Now receive reply from server
/*socket_recv ( $connection , $data , 2045 , MSG_WAITALL )*/
//socket_read($connection, 512, PHP_NORMAL_READ);
$input = socket_read($socket, $spawn, 1024);
echo $input . " INPUT";
$buffer = socket_recv($socket, $dataIn, 1024, 0);
echo $buffer . " buffer";
if(!socket_recv($socket, $dataIn, 1024, MSG_WAITALL)){
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not receive data: [$errorcode] $errormsg \n");
}
//print the received message
$response = unserialize($dataIn);
echo $dataIn;
//echo $buff;
socket_write($connection, $response);
//socket_close($connection);
}else{
echo "Error: ".socket_sterror($connection);
die;
}
}
I use windows 7 atm but the app will be run on unix system in command line. I open 2 cmd windows and start Server.php in first. I start Client.php in the second cmd window. I get the following errors (Server.php).
Socket created.
Socket bound.
Socket is listening...
Waiting for connections...
Yay !!! We have a connection
Client 127.0.0.1 : 50162 is now connected to us.
Connection is: Resource id #5
C:\Users\(myUsername here)\Desktop\sockets\Server.php on line 70
PHP Warning: socket_recv(): unable to read from socket [0]: The operation completed successfully.
in C:\Users\(myUsername here)\Desktop\sockets\Server.php on line 72
Warning: socket_recv(): unable to read from socket [0]: The operation completed successfully.
in C:\Users\(myUsername here)\Desktop\sockets\Server.php on line 72
PHP Warning: socket_recv(): unable to read from socket [0]: The operation completed successfully.
in C:\Users\(myUsername here)\Desktop\sockets\Server.php on line 75
Warning: socket_recv(): unable to read from socket [0]: The operation completed successfully.
in C:\Users\(myUsername here)\Desktop\sockets\Server.php on line 75
Could not receive data: [0] The operation completed successfully.
When I sent a string there was no problem. How do I have proceed with json data please ?
Was given the solution. I need to send json as string and it worked.
Client.php below
$jsonString = "";
$handle = fopen("C:\Users\(myUsername)\Desktop\sockets\Test.txt", "r");
if ($handle) {
while (($buffer = fgets($handle, 4096)) !== false) {
echo $buffer."\n";
//echo gettype($buffer)." buffer inside";
$jsonString.=$buffer;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
}
socket_write($sock, $jsonString);
fclose($handle);
Server.php below
$jsonString = "";
if(!socket_last_error($socket)){
while($buffer=socket_read($connection,2048)){
//echo $buffer;
$jsonString.=$buffer;
}
}
echo $jsonString;
I hope it can help someone and save some headache.

Wanting to run a section of php code repeatedly but without losing scope

So I've been able to use AJAX to repeatedly refresh a div on my website, using the following code:
var $container = $("#content");
var refreshId = setInterval(function()
{
$container.load('toad.php').fadeOut("slow").load('response.php').fadeIn("slow"); ;
}, 2000);
This works fine, toad.php gets executed every 2 seconds and the contents update.
toad.php contains the following code currently:
<?php
if ( !($sock = socket_create(AF_INET, SOCK_STREAM, 0)) ) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg \n");
}
echo "Socket created \n";
if (!socket_connect($sock, '127.0.0.1', 45000)) {
//$errorcode = socket_last_error();
//$errormsg = socket_strerror($errorcode);
echo "No sensor available to connect to.\n";
//die("Could not connect: [$errorcode] $errormsg \n");
}
echo "Connection established \n";
//Now receive reply from server
if (false !== ($bytes = socket_recv($sock, $buf, 1200, MSG_WAITALL))) {
echo "Read $bytes bytes from socket_recv(). Closing socket...";
}
else {
echo "socket_recv() failed; reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}
socket_close($sock);
echo $buf . "\n";
echo "OK.\n";
?>
The issue with this is that the socket is created and connected to every single time the div is refreshed.
If I don't have the socket_create and socket_connect functions in toad.php then the socket_recv function doesn't know about the socket and doesn't work.
My question is how can I get the socket receive code to loop and update the contents of the div without having to re create and connect to the socket every time?
Thanks!
If you can rewrite the server your connecting to to use websocket, you could just connect directly from the browser using socket.io.
http://socket.io/
As others have said, maintaining a persistent PHP connection can be tricky, but if running a NodeJS (or similar) script to handle client connections isn't possible you could serve the websockets from that same PHP script.
Try this approach:
http://devzone.zend.com/209/writing-socket-servers-in-php/
Your toad.php script would run on the command line, listening to your existing socket server, then serving the data to it's own socket server which the browser connects to directly with websocket.

Categories