Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: how to portably reserve a TCP port (so there will be a non-available URL)

I'm the maintainer of the XML-LibXSLT module and one of the tests needs to access a non-existing URL. Problem was that someone reported that on their system the URL existed, so I decided to allocate a random port on localhost where I'm sure there will be no web-service. It was done like that:

# We reserve a random port to make sure the localhost address is not
# valid. See:
#
# https://rt.cpan.org/Ticket/Display.html?id=52422

my $sock = IO::Socket::INET->new(
    Proto => 'tcp',
);

my $port = $sock->sockport();

$file = "http://localhost:${port}/allow.xml";

Now, the problem is that $port is defined and valid (to the value of a reserved port) on Linux, but it does not appear to work on Windows - see this bug report - https://rt.cpan.org/Ticket/Display.html?id=71456 . My question is: how can I reserve a new, random, not-yet-occupied port portably across UNIXes, Mac OS X and Windows in Perl 5?

Regards,

Shlomi Fish

like image 835
Shlomi Fish Avatar asked Oct 09 '11 14:10

Shlomi Fish


2 Answers

You should be able to bind to the loopback address using port 0 (so that a port will be allocated to you). For bonus points you may want to try to connect the socket to itself (probably not needed anywhere, but should guarantee that it has an address)

like image 139
Hasturkun Avatar answered Oct 29 '22 17:10

Hasturkun


You want to bind the socket to an address+port. This which will happen if you specify a LocalAddr (or LocalHost). If you don't specify a port (or you specify port zero), a free port will be picked for you.

use strict;
use warnings;
use 5.010;

use IO::Socket::INET qw( INADDR_ANY );

my $sock = IO::Socket::INET->new(
    Proto     => 'tcp',
    LocalAddr => INADDR_ANY,
);

my $port = $sock->sockport();

say $port;  # 60110

I think you want to only accept connections from the loopback adapter. If so, use INADDR_LOOPBACK instead of INADDR_ANY.

like image 28
ikegami Avatar answered Oct 29 '22 17:10

ikegami