Page 1 of 1

Socket Bind Error when running script from another PC

Posted: Sat Sep 30, 2006 1:16 am
by ckli6
Hi,

I have a form with 2 buttons, namely, Listen and Send, Send is for sending a Message to the remote host at the Port specified by the form, Listen is simply Creating a Socket, bind the port and listen for 3 seconds, if a message has been received, it will display the message on the HTML form. The protocol I am using is UDP.

I am testing this on an intranet with 2 PC's running XP, on my Server, I am using PHP 5.1 and IIS.

This is how I tested my script:

On the Server, run the script and 'Listen', on the other PC (client), run the script and Send a message to the Server, the script works fine and was able to display the incoming message properly.

However, if I start the script on the Client PC (ie not the one with PHP & IIS installed), when I press the Listen button, it will fail with the following message:

socket_bind: unable to bind address[0]:The requested address is not valid in its context.

Any ideas what's causing this.... below is the PHP Code that I'm using:

Code: Select all

<?php
   $host = $_SERVER['REMOTE_ADDR'];
   $post = 1001;
   set_time_limit(0);
   $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP) or die("Could not create socket\n");
 

   switch ($_POST['socktest']) {
     case 'Listen': {
       $buffer=' ';
       echo '<div id="mainbody"><p>Listening....</p></div>';
       echo '<div id="mainbody"><p>Received connection request.</p></div>';
       $result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
       socket_set_nonblock($socket) or die("Could not set non blocking mode.");
       $cont_flag = TRUE;
       $timeout = time() + ($wait_time); // 3 seconds timeout
         while ((time() <= $timeout) && $cont_flag) {
             @socket_recv($socket, $buffer, 100,  2); 
             if (@socket_recv($socket, $buffer, 100,  2)) {
               echo '<div id="mainbody"><p>Received Data from IP ' . $host .  ' : ' . $buffer .  ' </p></div>';
               echo '<div id="mainbody"><p>Total Bytes Received Data from IP ' . $host .  ' : ' . strlen($buffer) .  ' </p></div>';
               $in_msg = $host . ':' . $buffer ;
               $buffer = '';
               $cont_flag = FALSE;
             } else {
                continue;
             }
         } 
       echo '<div id="mainbody"><p>Closing sockets</p></div>' ;
       // close sockets
       socket_close($socket);
       break;
     }
     case 'Send': {
       socket_sendto($socket, $msg, strlen($msg), 0, $remote_host, $port);
       socket_close($socket);
       break;
     }
   }
?>
Thanks in advance!

Regards,
CK

Posted: Sat Sep 30, 2006 4:59 am
by volka
$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
Where do $host and $port come from?
Maybe like $_POST['socktest'] they are form data and stored in $_POST.

Posted: Sat Sep 30, 2006 7:31 am
by Mordred
1. $port = 1001;


2. $cont_flag = FALSE; is called "break" :)

3. While loop with no sleeping is a CPU hog. The correct way is to use

Code: Select all

socket_select()
4. Wouldn't calling socket_recv twice lose the first buffer?

Posted: Sat Sep 30, 2006 2:13 pm
by Chris Corbyn
I thought the socket functions only existed in CLI. Interesting :)

Posted: Sat Sep 30, 2006 6:22 pm
by Weirdan
Obviously you should pass the ip of the local interface to socket_bind(), not the $_SERVER['REMOTE_ADDR'].

Posted: Sat Sep 30, 2006 6:26 pm
by n00b Saibot
also $remote_host is not defined anywhere

Code: Select all

socket_sendto($socket, $msg, strlen($msg), 0, $remote_host, $port);

Posted: Sun Oct 01, 2006 2:26 am
by ckli6
Hi,

Thank you all for all the suggestions and pointers.

Actually, this script is embedded in an HTML form.
So these values are actually coming from the form: $port, $wait_time, $host (which will return the local pc's ip) and $remote_host.

One thing is: I've tried adding usleep(100000) in my while loop, but still the cpu utilization is 100% for the entire duration when it tries to read from the port.

I will try to using 'socket_select' and see how it goes.

But there is one thing I'm not sure and it's not clearly stated in the manual, before I use the socket_select function, do I need to bind the socket first? Or, the socket_select function will handle the bind automatically? Of course, I asssume the sockets must be declared first using socket_create befor issuing the socket_select.

Any ideas?

Thanks!

Regards,
CK

Posted: Sun Oct 01, 2006 4:52 am
by volka
ckli6 wrote:So these values are actually coming from the form: $port, $wait_time, $host (which will return the local pc's ip) and $remote_host.
That's only true for old versions of php or if register_globals is on (since php 4.2 it defaults to off)
see http://de2.php.net/security.globals

Posted: Sun Oct 01, 2006 4:56 am
by Mordred
bind() first.

create(), bind(), set_nonblock(), select() -> recvfrom()/sendto(). Oh yeah, don't use recv(), use recvfrom(), that's the right way of getting the remote sender, what you are doing currently is only correct if both scripts are on the same server.

Posted: Sun Oct 01, 2006 8:44 am
by ckli6
Mordred wrote:bind() first.

create(), bind(), set_nonblock(), select() -> recvfrom()/sendto(). Oh yeah, don't use recv(), use recvfrom(), that's the right way of getting the remote sender, what you are doing currently is only correct if both scripts are on the same server.
Thank you, Mordred.

I'll take your approach and give it a shot... will report back later...

Regards,
CK