PHP: socket_connect is working, but not socket_bind - php

I am trying to connect via TCP Socket to a third party product. I am able to do so (and send a message successfully) with the following code:
if (isset($port) and ($socket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) and (socket_connect($socket, $address , $port)))
{
$text="Connection successful on IP $address, port $port";
$data = "<msg id=1>text</msg>" . $newline;
socket_send($socket, $data, strlen($data), MSG_DONTROUTE);
$text .= socket_strerror(socket_last_error());
socket_close($socket);
}
The down side is that I also need to listen on this socket. As I understand it, I first need to bind, rather than using connect. When I run the code below, I get this error when calling socket_bind
Only one usage of each socket address (protocol/network address/port) is normally permitted.
code (snippet from a TCP Class, I have verified that the IP address, port, etc are the same in both snippets):
$this->Socket = socket_create(AF_INET, SOCK_STREAM, 0);
$result = socket_bind($this->Socket, $this->Host, $this->Port);
$result = socket_listen($this->Socket, 3) or die("Could not set up socket listener\n");
$spawn = socket_accept($this->Socket) or die("Could not accept incoming connection\n");
How is it that I can connect using socket_connect but not socket_bind? Is it correct that I need to use socket_bind if I want to listen on this socket?
I am running PHP on a Windows XP Apache installation (Zend). I should also mention that the only other application running when I try to execute this code is the third party program to which I am trying to connect.
Thank you for any insight.

Related

Cannot connect to IP using sockets

I am trying to connect to my public IP address but to no success.
The port is open as checked using - http://www.yougetsignal.com/tools/open-ports/
and a request from this site (http://www.rexswain.com/httpview.html) works.
My problem is with this PHP code below. This used to work fine when used on my local network. Now I am using it on a web server.
Could the problem be with the web server to allowing the request to be sent or am I doing something wrong?
$ip = "MYIP";
$port = "600";
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//socket_bind($sock, $ip, $port) or die ("cannot bind to address.");
echo($ip);
$state = socket_connect($sock,$ip, $port);
$error = socket_last_error();
$errorMsg = socket_strerror($error);
echo($errorMsg);
EDIT : The error in my comment below was derived with the socket_bind commented (Code edited to output the error)
Error : Connection timed out
This is wrong:
socket_bind($sock, $ip, $port) or ...
$state = socket_connect($sock,$ip, $port);
Bind binds the local address of the socket, it doesn't make sense to bind and connect to the same port. In general you do not want to bind in client mode. Remove the line completely, then you may get real error.

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 - listen on the "internet"?

Using the example from http://www.codeproject.com/Tips/418814/Socket-Programming-in-PHP
SERVER.PHP:
// set some variables
$host = "127.0.0.1";
$port = 25003;
// 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);
CLIENT.PHP:
$host = "127.0.0.1";
$port = 25003;
$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);
As you can see, the server is listening on 127.0.0.1:port and client is connecting to 127.0.0.1:port
However, I want my client and server to be on two different servers.
For example:
My server will listen be on IP 11.22.33.44:1234 and my client will be connecting from IP 12.23.45.66:1234
I am going to be using linux servers, but right now I am doing this on my windows machine.
So I want to listen on my external IP.
When I enter my external IP as host, I get errors thrown.
Warning: socket_bind(): unable to bind address [10049]: The requested address is not valid in its context. in C:\xampp\htdocs\server.php on line 12
Warning: socket_listen(): unable to listen on socket [10022]: An invalid argument was supplied. in C:\xampp\htdocs\server.php on line 14
Warning: socket_accept(): unable to accept incoming connection [10022]: An invalid argument was supplied. in C:\xampp\htdocs\server.php on line 17
Warning: socket_read() expects parameter 1 to be resource, boolean given in C:\xampp\htdocs\server.php on line 18
Warning: socket_write() expects paramet
er 1 to be resource, boolean given in C:\xampp\htdocs\server.php on line 20
How can I do this?
Thanks.
Since you're (speculation!) probably hosting this service behind a proxy, router, firewall, or other perimeter device, your box won't have direct access to bind to the external IP. Therefore, leave it bound to localhost and forward (open) the applicable ports from the perimeter device to your server.
If, for example, you're using AWS to host, you would set the firewall ACL to permit your socket ports to both servers and then the connections should flow through.
This is akin to binding your Apache web services to the localhost IP address of the server.
Alternatively, if you're not hosting this and communication is happening on a local network, then you should be able to at least bind to the assigned/internal IP address of each local network card.
open cmd and write that
php -f C:\xampp\htdocs\server.php
your code

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;
}
?>

PHP sockets problem

Hey guys, I am trying to do some socket programming in PHP.
So I am running a socket "server":
$address = '127.0.0.1';
$port = '9999';
$masterSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($masterSocket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($masterSocket, $address, $port);
socket_listen($masterSocket, 5);
$clientSocket = socket_accept($masterSocket);
So I open up SSH and run this script. It is running, no errors.
Then I have another PHP script which attempts to connect to this:
$fp = fsockopen("me.com", 9999, $errno, $errstr, 30);
fclose($fp);
but it's giving me:
Warning: fsockopen(): unable to connect to me.com:9999 (Connection refused)
How do I begin to fix this?
You haven't finished the listening socket sequence, you need to call socket_accept to accept new connections. There is an example in the comments in the PHP documentation.
$clients = array();
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($socket,'127.0.0.1',$port);
socket_listen($socket);
socket_set_nonblock($socket);
while(true)
{
if(($newc = socket_accept($socket)) !== false)
{
echo "Client $newc has connected\n";
$clients[] = $newc;
}
}
http://php.net/manual/en/function.socket-accept.php
1) Check if the port is firewalled off. You could use telnet to check this.
2) See if it works when the client and server are on the same machine (I'm guessing from your mention of SSH that the server is remote).
3) If it works locally and you can hit the remote port using other tools then it's going to be tricky. I'd suggest you wail and gnash your teeth for a bit; I'm out of ideas.
EDIT: Heh. Or you could just read Steve-o's answer. Teeth-gnashing is still an option.
I know you said that "me.com" is an example but, just to be sure, socket_bind is expecting an IP address.
From http://php.net/manual/en/function.socket-bind.php :
address
If the socket is of the
AF_INET family, the address is an IP
in dotted-quad notation (e.g.
127.0.0.1).
If the socket is of the AF_UNIX
family, the address is the path of a
Unix-domain socket (e.g.
/tmp/my.sock).
I know the question is very old, but if someone still has this problem, make sure you connect to the SAME address you are listening on,
For example, If you're listening on 127.0.0.1 and your Machine address is me.com, you won't be able to connect to me.com with it, for that you'll have to listen on me.com.
Listening on: localhost:8088
Can only connect via: localhost:8088 // not via me.com:8088
Listening on: me.com:8088
Can only connect via: me.com:8088 // not via localhost:8088

Categories