php - how to create a socket server in my webhost - php

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.

Related

Execute a PHP script only for fixed time

I have a function which creates a socket connection and listens on a port number for HL7 messages sent by a laboratory machine via TCP.
If the lab machine is not sending anything, my listen function keeps listening. Is there a way to specify that it should listen only for say 10 seconds and then if there are no messages, an error should be thrown?
$address = '0.0.0.0';
$port = 5600;
// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
$bind = socket_bind($sock, $address, $port);
// Start listening for connections
socket_listen($sock);
$client = socket_accept($sock);
// Read the input from the client
$input = socket_read($client, 2024);
// Strip all white spaces from input
$segs = explode("|",$input);
// Close the master sockets
$close = socket_close($sock);
This is the solution:
socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,array("sec"=>10,"usec"=>0)); // after 10 seconds socket will destroy the connection. Also you can set and uses
This looks like the XY problem.
That the thing you want to measure acts as a client rather implies that you might want to do more than just detect an open TCP connection in your script, e.g. capture some data. Further, the underlying OS has a lot of complex, well tested, reliable and tunable mechanisms for tracking the state of connections.
While you could do as stefo91 suggests and try to manipulate receive timeout, I'm not sure if this is applied in the wait for an initial connection. A better solution would be to set the socket to non-blocking. Don't forget to either:
inject some calls to sleep()/usleep() or
use socket_select()
unless you want your script to be burning a lot of resource with nothing to do.
But depending on a lot of information you've not told us about, the right solution might be to run one script as a server, and a second as a monitor. The second could be polling/parsing the output of netstat to check the connection.

Host a PHP Socket server program in AWS

My requirement is to host a php socket server script in AWS EC2. and communicate to that socket server. This is what I have done so far but its not working.
server.php script that acts a socket server and listens to clients:
<?php
// set some variables
$host = "127.0.0.1";
$port = 53;
// don't timeout!
set_time_limit(0);
// 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);
In AWS security group, I have added following Inbound rule:
I run the server,php script from SSH using command "php server.php".
I tried to connect to the server from SocketTest tool where I entered following
value
host: 52.xx.xx.xxx (masked the actual value here) and port: 53
I am not able to connect to the socket server. It would be really helpful if someone can guide me if I am missing anything here
Please note that same server.php program is working fine when tested in local xampp server
You have used '127.0.0.1' as host in server script.
You have to replace it with your server's private IP address.

what is socket in php? And at what condition i should go for socket connection?

I have already gone through some tutorials for socket but i couldn't get what it does. I want to know what sockets do and why is it used. This is the code I have referred.
client.php
<?php
$host = "localhost";
$port = 1024;
$message = "Hello Server";
echo "Message To server :".$message;
// create socket
$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
socket_close($socket);
?>
server.php
<?php
// set some variables
$host = "localhost";
$port = 1024;
// don't timeout!
set_time_limit(0);
// 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);
?>
So I couldn't get the idea of where to enter the server code and client code. Usually we write server code on what it should do while getting user input.So i am extremely confused about this. Can anyone help me? Thanks in advance
In order to understand sockets I think it's important to understand networking principles. Especially the Internet Protocol and Transmission Control Protocol.
The Transmission Control Protocol is a way of breaking up a message into smaller chunks, and addressing them in such a way that the chunks can be reliably re-assembled at the receiving end. The Internet Protocol is a way of routing these chunks through the Internet.
A Socket is just a programming object that manages the details of these protocols for you. You configure the socket to connect to a given port on a given IP address. The socket manages the rest: chunking, packaging, and labeling the data. The socket encapsulates all the protocol details so that you can abstract them away and act as if you are creating a "connection" from one computer to another. As a developer, you use sockets when you need to exchange information with another computer over the Internet.
For me, the idea of a socket and what it might be used for didn't make sense until I studied computer networking. (Especially the protocols themselves, not necessarily the practical, technician side of things.) You can start with the Wikipedia articles on TCP and IP. And you can try to read individual, piecemeal articles on the web. But frankly, networking is such a huge topic that I don't think anything short of a cohesive, semester-long course or a quality textbook would be enough to truly answer this question (and to correct the gaps, oversimplifications, and exceptions that I used to keep this answer simple.)
You need to understand the concept of socket programming. To get a better idea.
Sockets are used for interprocess communication. Interprocess
communication is generally based on client-server model. In this case,
client-server are the applications that interact with each other.
Interaction between client and server requires a connection. Socket
programming is responsible for establishing that connection between
applications to interact.
Client application sends message($message) to server($host) and the
server application receives it from the client through a port($port).
The client.php runs and sends the message from a client machine. The server.php runs on the server machine which receives the message.
Try these links for examples and how to run the server and client files.
http://www.binarytides.com/php-socket-programming-tutorial/
http://www.devshed.com/c/a/php/socket-programming-with-php/

Error using socket_bind() on a shared hosting provider

I have a server service script and client service script written in PHP using PHP's sockets API. They are working fine in localhost, but after uploading those two scripts to my hosting account on ipage, the server script is giving me an error on the socket_bind call. Here is the code I am using on the server:
$host = "my_own_hosting";
$port = 25003;
$message = "Hello Client";
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0)
or die("Could not create socket\n");
// bind socket to port (this is the call that returns the error)
$result = socket_bind($socket, $host, $port)
or die("Could not bind to socket\n");
// put server into passive state and listen for connections
$result = socket_listen($socket, 3)
or die("Could not set up socket listener\n");
Any ideas on why this call is not working?
First and foremost:
Use socket_strerror and socket_last_error to figure out your problem:
if (!($result = socket_bind($socket, $host, $port)){
die(socket_strerror(socket_last_error($socket)));
}
You are trying to run your server script on a shared PHP hosting provider (ipage).
These kind of providers do not generally allow to use the PHP sockets interface to build your own services, or implement harsh restrictions (Such as allowed ports or protocols for running the service) to avoid abuse and prevent safety issues. Either you comply with them or change your hosting service to one that fits your needs.
It seems your provider allows using the sockets interface though.
(You can check it out by searching for socket on http://www.hostingreviewbox.com/features/ipage-php/ although it's best if you make sure of it by running phpinfo on your account yourself, or even better: Open up a support ticket with your hosting provider and ask them if sockets are in any way restricted on your account.)
Then you should make sure of 2 things:
Are you using the proper ip address on $host?
You can ping my_own_hosting and see what you get or even better, add this code snippet to your server script for figuring out your server's public ip at runtime:
$host = my_ip();
echo "my ip address is $host\n";
function my_ip($dest='8.8.8.8', $port=53)
{
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_connect($socket, $dest, $port);
socket_getsockname($socket, $addr, $port);
socket_close($socket);
return $addr;
}
(from http://php.net/manual/en/function.socket-create.php#49368)
Is the port you are trying to use already in use or restricted?
Try to use a different port or ask your hosting provider about it.
On a side note:
Trust the PHP manual before its comments: You should use getprotobyname or SOL_TCP for determining the third parameter of socket_create instead of just sending 0.
Lastly, you should consider using socket_create_listen instead of socket_create + socket_bind + socket_listen. Or, for this particular case, stream_socket_server and stream_socket_accept. Like the PHP manual shows, they are way more practical:
$socket = stream_socket_server("tcp://{$host}:{$port}", $errno, $errstr);
if (!$socket) {
echo "$errstr ($errno)<br />\n";
} else {
while ($conn = stream_socket_accept($socket)) {
fwrite($conn, 'The local time is ' . date('n/j/Y g:i a') . "\n");
fclose($conn);
}
fclose($socket);
}

PHP Sockets - can only connect from localhost (Port Forwarding problem?)

First of all, thanks for taking the time to read this. I have a strange problem with PHP sockets. I working on a php socket daemon which works via localhost, but when I try to connect from outside the LAN or another PC, it doesn't work. I've simplified my daemon to a very basic socket connection to replicate the issue for you to see.
Basically, here's the senario. I start the socket daemon on my server on port 6667. I can connect to the daemon via telnet and from the browser on the local machine running the daemon, but I cannot from any other machine - the daemon doesn't even see a connection attempt being made.
To further complicate the issue (which is why I think it's a port forwarding issue), my ISP blocks port 80, so I've setup dyndns and my router to use port 8000. I've also setup my router to forward port 6667 to my server.
To access my daemon from a browser, I enter the following (seudo) url:
http://mydomain.com:8000/client.php
This works from the local machine and will connect, but from any other machine, the daemon doesn't even see a connection attempt being made. However, if I specify the port like this:
http://mydomain.com:6667
my daemon does see a connection being made, but of course then the browser doesn't have a client page loaded that the user can use to interact with the daemon.
My client uses a flash file to create the socket connection (jsocket), but I know it isn't the cross-domain policy file because the policy is correct, and when connecting via localhost, it serves the policy file correctly.
Here's the simplified daemon code:
<?
// set some variables
$host = '0.0.0.0';
$port = 6667;
// don't timeout!
set_time_limit(0);
// 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 input back
$output = $input . "\n";
socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n");
// close sockets
socket_close($spawn);
socket_close($socket);
?>
Summary:
I CAN connect from localhost via telnet and browser... I CAN connect from other machines via telnet, but I CAN NOT connection from the browser from other machines using the ip or domain name when port 8000 is specified. The daemon doesn't see any connection attempt. If I specify port 6667, then the daemon see's a connection attempt, but that is useless to the user. :(
Any help in this matter would be greatly appreciated! Thanks!
You're binding the socket (using socket_bind) onto localhost. Supplying localhost there will have PHP bind the socket to the 127.0.0.1.
socket_bind is used to bind a socket to a specific interface. Per example:
socket_bind($socket, '127.0.0.1', 80);
This allows you to connect to 127.0.0.1:80, but not 192.168.1.100:80, even if they are the same machine. The socket is bound to the 127.0.0.1 interface only:
$ telnet localhost 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
$ telnet 192.168.1.100 80
Trying 192.168.1.100...
telnet: Unable to connect to remote host: Connection refused
If you want to bind the socket on all available interfaces, use:
socket_bind($socket, '0.0.0.0', 80);
Then this works:
$ telnet localhost 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
$ telnet 192.168.1.100 80
Trying 192.168.1.100...
Connected to 192.168.1.100.
I use this "port_forwarding.php" on server to open port 3000 and forward remote mysql client connection to unix socket file / port 3306 of mysql server:
<?
set_time_limit(0);
function shutdown()
{global $ipsock, $rmsock;
if ($ipsock) fclose($ipsock);
if ($rmsock) fclose($rmsock);
}
register_shutdown_function('shutdown');
$target_socket='unix:///tmp/mysql.sock';//or 'tcp://192.168.0.2:3306'
$ipsock=stream_socket_server('tcp://192.168.0.2:3000', $errno2, $errstr2);
stream_set_blocking($ipsock, 0);
while (true)
{usleep(5000);//0.005s, to reduce cpu consumption
$c_ipsock=stream_socket_accept($ipsock); //even add '-1', it won't wait
$rmsock=stream_socket_client($target_socket, $errno, $errstr);
#stream_set_blocking($rmsock, 1);
while (($c_ipsock && !feof($c_ipsock)) && ($rmsock && !feof($rmsock)))
{$swrite=$except=null;
$sread=array($c_ipsock, $rmsock);
stream_select($sread, $swrite, $except, 5);
//print_r($sread);echo " \n";
if ($sread[0]===$rmsock)
{if ($data=fread($rmsock, 65536))
{//echo 'rmsock:'.strlen($data).' '.$data." \n";
myfwrite($c_ipsock, $data);
}
}
else if ($sread[0]===$c_ipsock)
{if ($data=fread($c_ipsock, 65536))
{//echo 'ipsock:'.strlen($data).' '.$data." \n";
myfwrite($rmsock, $data);
}
}
//var_export(array(feof($c_ipsock), feof($rmsock)));echo " \n";
}
#fclose($c_ipsock);
#fclose($rmsock);
}
function myfwrite($fd,$buf) {
$i=0;
while ($buf != "") {
$i=fwrite ($fd,$buf,strlen($buf));
if ($i==false) {
if (!feof($fd)) continue;
break;
}
$buf=substr($buf,$i);
}
return $i;
}
?>

Categories