eyepopslikeamosquito has asked for the wisdom of the Perl Monks concerning the following question:

To compare and report on file handles stored in various data structures, I'd like to uniquely identify a Perl file handle. I noticed that running:

open my $fh, '<', $0 or die "error: open '$0': $!"; my $fh_hex = sprintf '0x%x', $fh; printf "fh='$fh' fh_hex='$fh_hex'\n";
produces:
fh='GLOB(0x202068)' fh_hex='0x202068'

So I suppose I could use $fh_hex above as a string that uniquely identifies a file handle. Is there a better way?

Replies are listed 'Best First'.
Re: Hex value of Perl file handle to uniquely identify
by BrowserUk (Patriarch) on Apr 09, 2016 at 06:12 UTC

    Depends what you mean by "uniquely"? Ie. Is it the internal handle you're interested in; or where it is pointing:

    C:\test>perl -mstrict -wle"print \*STDERR; open STDERR, '>', 'junk.err +' or die $!; print \*STDERR;" GLOB(0x1da110) GLOB(0x1da110)

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.

      The value of the internal file handle should suffice. To give some background, I am writing a simple mock tcp server, using IO::Socket::INET and IO::Select, to use in system testing. It is not finished yet, but as a minimum I'd like to at least display the socket ids in a trace so I can tell which client is sending what. Here are some (incomplete) code snippets to give you a feel:

      my $listener = IO::Socket::INET->new( LocalPort => $port, Proto => 'tcp', Listen => 5, ReuseAddr => 1, ) or die "error: IO::Socket::INET: $@"; my $selector = IO::Select->new($listener); while ( my @ready = $selector->can_read() ) { for my $client (@ready) { if ( $client == $listener ) { my $new_conn = $listener->accept(); $selector->add($new_conn); my $fh_hex = sprintf '0x%x', $new_conn; print "Accepted new connection ($fh_hex)\n"; # ... sub recv_client { my $client = shift; my $fh_hex = sprintf '0x%x', $client; print "Recv from client ($fh_hex):\n"; # ... display data received ... }

      Update: Thanks to BrowserUk's excellent tip I am now using:

      my $fh_hex = sprintf '0x%x', $new_conn; my $peerhost = $new_conn->peerhost(); my $peerport = $new_conn->peerport(); my $peeraddr = $new_conn->peeraddr(); my $peerhostfull = gethostbyaddr($peeraddr, AF_INET) || "Cannot resolv +e"; print "Accepted new connection $fh_hex ($peerhost:$peerport,host=$peer +hostfull)\n";
      which is much better.

        Be aware that handles do get reused. Once a client disconnects, the next connect might reuse that handle.

        For uniqueness, you might consider combining the output from IO::Socket's PeerHost() and PeerPort() methods: xxx.xxx.xxx.xxx:nnnn.

        Also, I don't see a lot of value in sprintfing the handle, over the default stringification 'GLOB(0xHHHHHH)"?


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.
        $unique{$new_conn}++; $unique_id = "$client $unique{$client}";

        glob plus counter per glob

Re: Hex value of Perl file handle to uniquely identify
by haukex (Archbishop) on Apr 09, 2016 at 10:08 UTC

    Hi eyepopslikeamosquito,

    There's also fileno, but those numbers are re-used. I don't have much experience with fileno, so perhaps a monk who does can say more, but I imagine that if you closely keep track of when filehandles are closed, you could still use fileno to tell different connections apart.

    open my $fh1, '<', '/tmp/foo' or die $!; open my $fh2, '<', '/tmp/bar' or die $!; print "fh1: ", fileno($fh1), "\n"; print "fh2: ", fileno($fh2), "\n"; __END__ fh1: 3 fh2: 4

    Otherwise, I agree with BrowserUk: a good way to identify network connections is by properties like remote IP + remote port.

    A while back I tried out POE. Its API takes quite a bit of getting used to, but once you've got the hang of it, it works well. Since each "session" has a unique ID, keeping track of clients is easy. The Cookbook is really helpful in getting started.

    Hope this helps,
    -- Hauke D

Re: Hex value of Perl file handle to uniquely identify
by james28909 (Deacon) on Apr 09, 2016 at 16:16 UTC
    Please forgive my ignorance, but could you not build a hash of clients and assign it a random number for uniqueness? like for($new_conn){ $hash{$new_conn} = unique_value();} and do functions on unique values in the hash.