Suppose you use PHP’s fsockopen method in your code. For example you want to send POST requests to a remote server. Chances are you’ve got something like this:
$socket = @fsockopen('ssl://xmlapi.example.org' , 9090 , $errno , $errstr , 30);
There is nothing wrong with this code, but if your web server listens to multiple IP addresses, you might not be happy with the default IP used for the outgoing connection to the remote server. In this case you might want to specify the IP address, that is used by PHP to send the request.
Alright, the title of the post is a bit misleading. Actually, you can’t bind sockets opened with fsockopen to a specific IP address. But you can use the methods stream_context_create and stream_socket_client to open a socket that can be used equal to a socket opened by fsockopen. You can use the ressource handle $socket returned by stream_socket_client like a source handle returned by fsockopen. The drawback is, that these methods are only available since PHP version 5. But as PHP version 4 is no longer supported by the PHP team, you should switch anyway, if you haven’t already.
The following code tests, if the methods in question are supported by your PHP installation. If so, they bind the socket to the IP address 192.0.2.1. :0 means, that we do not care about the outgoing port number used by the socket. You could specify a specific port here, too.
if (function_exists('stream_context_create') && function_exists('stream_socket_client')) {$socket_options = array('socket' => array('bindto' => '192.0.2.1:0'));$socket_context = stream_context_create($socket_options);$socket = stream_socket_client('ssl://xmlapi.example.org:9090', $errno,$errstr, 30, STREAM_CLIENT_CONNECT, $socket_context);} else {$socket = @fsockopen( "ssl://xmlapi.example.org" , 9090 , $errno , $errstr , 30 );}
The only requirement is, that your web server is configured to listen to the IP you want to bind the socket to. If you specify a specific port number, the port number must not be used by another service. It must be a port above 1024 also. Unless your web server runs as root, which would be a big security problem.
Shameless plug: If this post was useful to you, please consider buying yourself something from one of my Amazon stores: US store, UK store, FR store, DE store, CA store. If you're not into Amazon, why not donate something to GNOME, Mozilla or Wikipedia? Thank you!



Hi,
Nice and great solution.
But now i am using php 4.3. stream_socket_client() only available on php 5.
Do you have any ideas, please?
Thanks
steven
You could use the socket_*() methods of PHP. These are available in PHP >= 4.0.7. Have a look at example #1 in the socket_bind() documentation of PHP. The drawback is, that you can’t use the socket returned like a source handle returned by fsockopen(). You need to rewrite your code to use the appropriate methods (socket_write(), socket_read()).
Worked great! Thanks for the simple intro on use socket_bind_*
Works like a charm !
Thanks !
for those of you looking to make Invision Power Board 3.0 (IPB 3.0, or IP.Board 3.0) work with gmail and bind to a specific IP address to send mail, the following code will be useful.
from classEmail.php:
comment out line 984 and replace with the following ( replacing with the ip you would like to bind naturally. ):
if (function_exists(‘stream_context_create’) && function_exists(‘stream_socket_client’)) {
$socket_options = array(‘socket’ => array(‘bindto’ => ‘:0′));
$socket_context = stream_context_create($socket_options);
$socket = $this->smtp_fp = stream_socket_client(‘tls://smtp.gmail.com:465′, $errno,
$errstr, 30, STREAM_CLIENT_CONNECT, $socket_context);
}
Thanks for the solution. Unfortunately I am at a reseller environment at Hostgator, and, although I have purchased and installed a unique IP address for my website, I can’t change the IP with stream_context_create & stream_socket_client (I receive an access denied error)
Works great! With this, I was able to modify PHPMailer so that I can choose the IP address used to send mail on a per-message basis. (Seems silly, but yeah, I needed it for a project I am working on.)
[...] [...]
I used ‘google.com’ instead of ‘ssl://xmlapi.example.org:9090′ and it returned error “Failed to parse address “google.com”‘?. then I used ‘http://google.com‘ and it returned “Unable to find the socket transport “http” – did you forget to enable it when you configured PHP”. What I should use for http links?
?
Try tcp://google.com:80 However, if you want to talk to Googles web server, you’ll need to submit the HTTP requests yourself. PHP will open a connection to the server, but the rest is up to you.