Welcome to WebmasterWorld Guest from 54.225.3.114

Forum Moderators: coopster & jatar k

Message Too Old, No Replies

Playing With Sockets With PHP

     
9:02 am on Nov 14, 2013 (gmt 0)

Junior Member

10+ Year Member

joined:Nov 22, 2004
posts: 120
votes: 0


I'm trying to whip up some PHP that will open a TCP socket connection to a specified port on a specified host. That's all I'm doing is opening the connection, then closing it. I'm essentially just sniffing ports so I don't need to send or receive any data. I know of two ways to do this:
  1. fsockopen()
  2. socket_create(), socket_connect()


But as with all things in life, things get hung up in the details. There are two very important 'features' that I need.

First, I need to be able to bind this outgoing connection to alternate IP that my server has. This website is running on it's own unique IP, and this IP is not the server's default IP. So I'd like all outgoing connections from this site to also use this unique IP. As it turns out, you can bind to an IP using socket_bind() with the socket_create() function. It works nice and easy.

Second, I need to set a connection timeout. Not a read/write timeout, because I'm not actually reading or writing anything. I'm just opening the connection, and then closing it. So I need a way to apply a timeout to that process. As it turns out, fsockopen() supports connection timeouts by default, just stick an int as the 5th argument when calling the function. Nice and easy.

But the problem is that (as far as I've been able to learn), you can't bind to an IP with fsockopen() and you can't set a connection timeout with socket_create()/socket_connect(). Here is the code I have. I tried both techniques, but each one has it's corresponding flaw as mentioned above. using socket_create(), i've even tried setting the default_socket_timeout ini value using ini_set() but nothing seems to have any effect.

I've also read somewhere that I could possibly make socket_connect() connect using a non blocking connection. Which would not hold up the script while the connection is attempted. This why, I could simply give up waiting for a result after my $timeout. The problem is, other than casual mentions, I haven't been able to find any documentation or sample code of how you'd actually DO this. I don't know if it would even work.

So here is my original code, using fsockopen(). It has a connection timeout and it works great, except that the connections are coming from the wrong IP address because I haven't found any way to bind these connections to another IP address.

$sock = @fsockopen($ip,$port,$errno,$errstr,$timeout); if ($sock) { // Open fclose($sock); return 1; } else { if ($errno === 60) { // Timeout return 2; } else { // Closed return 3; } }

Here was my second try using socket_create() and socket_connect(). These connections are bound to the proper IP address, but there is no way to set a connection timeout. This means that if the port is blocked by a firewall, my PHP script will keep running for about 45 seconds until it gives up. In this code, I even tried setting the read and write timeouts to see if that would work, but it does not. Nor does setting the default_socket_timeout value.

ini_set("default_socket_timeout",$timeout); $sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); socket_bind($sock,OPERATING_IP); socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec" => $timeout, "usec" => 0)); socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array("sec" => $timeout, "usec" => 0)); $sock_status = @socket_connect($sock,$ip,$port); if ( $sock_status ) { // Open socket_close($sock); return 1; } else { $sock_error = socket_last_error($sock); if ($sock_error === 61) { // Closed return 3; } else { // Timeout return 2; } }

Anyway, this is my dilemma. I'm sure there must be some way to make this work, but it seems like PHP socket functions just aren't used that much, and because of that, they don't have nearly as much documentation and sample code across the internet.

[edited by: phranque at 11:35 pm (utc) on Dec 26, 2013]
[edit reason] syntax=php [/edit]

5:09 pm on Dec 26, 2013 (gmt 0)

Administrator

WebmasterWorld Administrator coopster is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:July 31, 2003
posts:12547
votes: 2


I looked at this for a bit today and couldn't come up with a quick answer either, l008comm. Have you considered cURL instead maybe?
7:32 pm on Dec 26, 2013 (gmt 0)

Senior Member from GB 

WebmasterWorld Senior Member brotherhood_of_lan is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Jan 30, 2002
posts:4863
votes: 13


cURL does allow you to choose the network interface and it's quite easy to use.

curl_setopt($handle,CURLOPT_INTERFACE,$interface_or_ip_to_use);
11:15 pm on Dec 26, 2013 (gmt 0)

Junior Member

10+ Year Member

joined:Nov 22, 2004
posts: 120
votes: 0


Everyone suggests this on every forum I've posted this on. But I'm not downloading anything, I'm opening a connection on a tcp port, then closing it. Can you really ports can like that with curl? I don't think so?
11:38 pm on Dec 26, 2013 (gmt 0)

Administrator

WebmasterWorld Administrator phranque is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Aug 10, 2004
posts:10858
votes: 67


seems like socket_set_option should have done the job.
i would add proper error checking everywhere and try socket_set_option before socket_bind as in the example.

PHP: socket_set_option - Manual:
http://www.php.net/manual/en/function.socket-set-option.php [php.net]

also, i'm not a php expert, but "@socket_connect"?