3

I have php cli socket server with the code below; clients connect and send requests

<?php
// PHP SOCKET SERVER
error_reporting(E_ERROR);
// Configuration variables
$host = "127.0.0.1";
$port = 5600;
$max = 500;
$client = array();

// No timeouts, flush content immediatly
set_time_limit(0);
ob_implicit_flush();

// Server functions
function rLog($msg){
             $msg = "[".date('Y-m-d H:i:s')."] ".$msg;
             echo($msg."\n");

}
// Create socket
$sock = socket_create(AF_INET,SOCK_STREAM,0) or die("[".date('Y-m-d H:i:s')."] Could not create socket\n");
// Bind to socket
socket_bind($sock,$host,$port) or die("[".date('Y-m-d H:i:s')."] Could not bind to socket\n");
// Start listening
socket_listen($sock) or die("[".date('Y-m-d H:i:s')."] Could not set up socket listener\n");

rLog("Server started at ".$host.":".$port);
// Server loop
while(true){
             socket_set_block($sock);
             // Setup clients listen socket for reading
             $read[0] = $sock;
             for($i = 0;$i<$max;$i++){
                          if($client[$i]['sock'] != null)
                                       $read[$i+1] = $client[$i]['sock'];
             }
             // Set up a blocking call to socket_select()
             $ready = socket_select($read,$write = NULL, $except = NULL, $tv_sec = NULL);
             // If a new connection is being made add it to the clients array
             if(in_array($sock,$read)){
                          for($i = 0;$i<$max;$i++){
                                       if($client[$i]['sock']==null){
                                                    if(($client[$i]['sock'] = socket_accept($sock))<0){
                                                                 rLog("socket_accept() failed: ".socket_strerror($client[$i]['sock']));
                                                    }else{
                                                                 rLog("Client #".$i." connected");
                                                    }
                                                    break;
                                       }elseif($i == $max - 1){
                                                    rLog("Too many clients");
                                       }
                          }
                          if(--$ready <= 0)
                          continue;
             }
             for($i=0;$i<$max;$i++){
                          if(in_array($client[$i]['sock'],$read)){
                                       $input = socket_read($client[$i]['sock'],1024);

                                        if($input){

                                                    rLog("Client ".$i." Call:".$input.")");

                                                    ## <<<<<<<<<<< Clients Request Show Here >>>>>>>>>>>> ##
                                                    ## <<<<<<<<<<< Clients Request Show Here >>>>>>>>>>>> ##
                                                    ## <<<<<<<<<<< Clients Request Show Here >>>>>>>>>>>> ##
                                                    ## <<<<<<<<<<< Clients Request Show Here >>>>>>>>>>>> ##
                                                    ## <<<<<<<<<<< Clients Request Show Here >>>>>>>>>>>> ##

                                        }
                          }
             }
}
// Close the master sockets
socket_close($sock);
?>

Question:
- How can I detect the IP Address of clients connected to my php cli socket server ?

deefour
  • 34,974
  • 7
  • 97
  • 90
Root
  • 2,269
  • 5
  • 29
  • 58
  • Note that your code cant handle concurrent connections. If you want that, you have to use something that supports threading. I.e. node.js, etc – Ron Jul 18 '12 at 13:33
  • @Ron It *can* be done in PHP, but you are right in that you shouldn't, because it's a complete PITA and doesn't work very well in a uni-process, uni-thread environment. However it is also important to note that Node.js does *not* in fact support threading. Because it is Javascript based, everything is executed in a single process with a single thread (Hey, I hear you say, isn't PHP like that? Wait for it...), it simply *appears* to be threaded because of the way the Javascript scheduler works. You can, however, spawn new processes by creating WebWorkers - but these are still uni-threaded. – DaveRandom Jul 18 '12 at 13:43
  • @Ron Worthwhile further reading [here](http://ejohn.org/blog/how-javascript-timers-work/). The diagram sums it up very well, I feel. But then I wouldn't expect anything else from [John Resig](http://stackoverflow.com/users/6524/john-resig). – DaveRandom Jul 18 '12 at 13:45
  • Yes and no. Yes, node.js uses Javascript. No, node.js is not comparable with javascript in a browser. Node.js use an interessting callback model, that makes your programm's aspects event-driven. With that model, you can do things you cant with php's imperative programming model... – Ron Jul 18 '12 at 13:49
  • @Ron `you can do things you cant with php's imperative programming model` - Absolutely true, but because Node is based on the V8 engine it *can* be compared to Javascript in a browser - specifically Javascript in Chrome. And the same principals as said browser still apply - if you write a CPU-heavy JS function that takes 10 minutes to execute and run it in Node, that instance of Node won't be able to do anything else while it executes. Because most socket operations take <1ms, and a lot of I/O operations like this are subbed out to work threads, it never really becomes an issue. – DaveRandom Jul 18 '12 at 13:54

1 Answers1

4

Immediately after the line where you successfully call socket_accept(), put a call to socket_getpeername():

if (($client[$i]['sock'] = socket_accept($sock)) < 0) {
    rLog("socket_accept() failed: ".socket_strerror($client[$i]['sock']));
} else {
    rLog("Client #".$i." connected");
    socket_getpeername($client[$i]['sock'], $address, $port);
}

$address now contains the remote host's IP address, and $port contains the remote port. Do with that information as you will.

DaveRandom
  • 87,921
  • 11
  • 154
  • 174