Building network services with PHP and xinetd

Not all is web and HTTP. Sometimes we need to create a network service listening to a port. We can create a TCP server in C, Java or even PHP but there’s a really helpful daemon in Linux that helps us to do it. This daemon is xinetd. In this article we are going to create a network service with PHP and xinretd.

Now we are going to create our brand new service with xinetd and PHP. Let’s start. First we are  going to create a simple network service listening to 60321 port. Our network service will say hello. The PHP script will be very complicated:

// /home/gonzalo/tests/test1.php
echo "HELLO\n";

We want to create a network service on 60321 tcp port so we need to define this port on /etc/services. We put the following line at the end of /etc/services

// /etc/services
myService   60321/tcp # my hello service

And finally we create out xinetd configuration script on the folder /etc/xinet.d/ , called myService (/etc/xinetd.d/myService)

# default: on
# description: my test service

service myService
        socket_type             = stream
        protocol                = tcp
        wait                    = no
        user                    = gonzalo
        server                  = /usr/local/bin/php-cli
        server_args             = /home/gonzalo/tests/test1.php
        log_on_success          += DURATION
        nice                    = 10
        disable                 = no

Now we restart xinetd

sudo /etc/init.d/xinetd restart

And we have our network service ready:

telnet localhost 60321
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

Easy. isn’t it? But it may be not really useful. So we are going to change something in our php script to accept input. Here we cannot use POST or GET parameters (that’s not HTTP) so we need to read input from stdin. In PHP (and in other languajes too) that’s pretty straightforward.

$handle = fopen('php://stdin','r');
$input = fgets($handle);

echo "hello {$input}";

Now if we run our script from CLI it will ask for input.
So if we test our network service with a telnet.

And we have our network service ready:

telnet localhost 60321
Trying ::1...
Connected to localhost.
Escape character is '^]'.

we type: “gonzalo” and:

hello gonzalo
Connection closed by foreign host.

About Gonzalo Ayuso

Web Architect specialized in Open Source technologies. PHP, Python, JQuery, Dojo, PostgreSQL, CouchDB and node.js but always learning.

Posted on May 23, 2010, in Linux, php, Technology. Bookmark the permalink. 15 Comments.

  1. Great article.

    One question, if there was no CR coming in, just a fixed length 128 characters, some non printable, what would the php code look like?

  2. Excellent tutorial thanks!
    I have a question: how I can know the IP of the remote client?

    • Gonzalo Ayuso

      You can see the client IP with the same technique than with a http request: with $_SERVER[‘REMOTE_ADDR’]. You also must take into account that remote IP can be behind a proxy have a look to:

      • This is my code and the remote IP is always zero which is my mistake?

        $IpX = $_SERVER[‘REMOTE_ADDR’];

        $handle = fopen(‘php://stdin’,’r’);
        $input = fgets($handle);

        //Determinar longitud
        if (strlen($input) > 10) {

        //Base de DAtos
        //$IpX = ‘’;
        $hostname_localhost = “localhost”;
        $database_localhost = “database”;
        $username_localhost = “user”;
        $password_localhost = “pass”;
        $localhost = mysql_connect($hostname_localhost, $username_localhost, $password_localhost) or trigger_error(mysql_error(),E_USER_ERROR);

        $sqlQuery = “INSERT INTO hitser_gps.log (Ip,Log) VALUES (‘$IpX’,’$input’)”;

        $table = mysql_query($sqlQuery, $localhost) or die(mysql_error());


      • I use:

        $host = $_SERVER['REMOTE_HOST'] ? $_SERVER['REMOTE_HOST'] : $_SERVER['HOST'];

        In my local LAN

  3. Funciona !!! Maestro !!!! For several days searching for an answer …


  4. thanks, Gonzalo
    right now i’m considering my future PHP-daemon which should catch simple flags (like 0/1/2) and do things (like mysql SELECT/UPDATE, also useradd/userdel/untar archives etc).
    thing is – there will be much of connections and the number will grow up in time.
    so what about queues in this case? in nature PHP-daemon i can make forks with background jobs, i can work with queue but in case of xinetd what it’s gonna be?
    also it is possible (and will be good?) to keep opened connection to mysql?

    • PHP is single thread. Create threads in PHP is a nightmare (with PHP and with almost all languages) queues are good solution to this problems, and also xinet.d. I’ve got one small experiment building something similar (I will write a blog post about this project soon). Anyway I’m not 100% percent convinced with my own solution.

      xinet.d works fine. The problem is when you need to handle big amount of incoming connections. If you need to process 1..10 request per minute works great, but if you need to process, for example, 20 per seconds your server load will raise a lot. xinet.d will create one process per request. 20 process at the same time => server load = 20 and sysadmin will be angry (nevertheless sysadmins always are angry :). In those cases we need a dedicated server. Nowadays I’m using nodeJs or python servers when I need to do this kind of things. pxinetd is an experiment to do this with PHP and React library. Anyway it’s still single thread (aka one slow process will block the entire script). IMHO Queues are the solution. Gearman or maybe one custom queue with ZeroMQ

  1. Pingback: Webby Scripts Building network services with PHP and xinetd « Gonzalo Ayuso …

  2. Pingback: Sending sockets from PostgreSQL triggers with Python « Gonzalo Ayuso | Web Architect

  3. Pingback: Building TCP server daemond with PHP and Rachet | Gonzalo Ayuso | Web Architect

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Get every new post delivered to your Inbox.

Join 1,093 other followers

%d bloggers like this: