Search code examples
phpsocketslocalhost

Getting 'Address already in use' when I try to bind a socket to localhost in php


I'm trying to create a socket connection from a php script to a local server (Qt, QLocalServer) but I'm having trouble just creating a connection on the php side.

<?php
error_reporting(E_ALL);
ini_set('display_errors', 'On');


set_time_limit(0);
ob_implicit_flush();

echo 'usr='. get_current_user().'<br/>';

$address = 'localhost';
$port = 4444; //Different port numbers produce same result

if (($sock = socket_create(AF_UNIX, SOCK_STREAM, 0)) === false) 
{
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
    exit();
}

 if (socket_bind($sock, $address, $port) === false) 
{
    echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
    exit();
}

...

This results in

usr=root Warning: socket_bind(): unable to bind address [98]: Address already in use in /var/www/nbr/socket.php on line 28 socket_bind() failed: reason: Address already in use

I've tried a number of things which give indications of what the problem may be, but not how to resolve it. socket_getsockname produces garbage when I try to echo the address and port information, but if I change AF_UNIX to AF_INET, and add

$addr = ""; $pt = "";    
echo "Socket name ok: " . socket_getsockname($sock, &$addr, &$pt) . '<br/>';
echo $addr .    ", " . $pt . '<br/>';

the result is

Socket name ok: 1

0.0.0.0, 0

So is address/port just never set properly somehow? Also, subsequent socket_get_option($sock, 0, SO_REUSEADDR) fails with AF_UNIX, succeeds with AF_INET but I still get the address unavailable error.

What am I doing wrong?


Solution

  • socket_bind is used to bind a socket on the local machine. Binding a socket means reserve a address/port for a socket. You usually use it for a listener (server) not a client. In your case, since the server (Qt) is already started, then the address is already in use, so socket_bind will fail.

    If you want to connect to a socket, use socket_connect:

    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    if (!socket_connect($socket, 'localhost', 4444)) {
        die('failed');
    }
    

    If you want to connect to a local socket (i.e.: through a socket file, and not through TCP/UDP):

    $socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
    if (!socket_connect($socket, '/var/run/mysqld/mysqld.sock')) {
        die('failed');
    }