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

Dearest monks,

So I've recently made my first serious foray into socket programming. It's pretty cool, it makes me feel 31337. (Look! you can talk directly to the whois port!) Others aren't as excited as I am. . .

Anyway, besides always typing "sockey" when I type socket, I'm having one minor problem.

I'm trying to bind a client program to a specific IP, and I'm having trouble with the syntax. Normally, I would use IO::Socket, because it's easier, but in this case I need more control over my socket than IO::Socket would easily provide.

Anyway, the relevant code is below. I'm trying to automate a set of whois lookups, and I need to bind to different IPs on the same box ocassionally.

Is there anything jumping out at you? The docs aren't that great, the Camel mentions "you can bind a client to an address too" but then doesn't really go into details. What I have below seems like the most logical solution but doesn't work.

This is possible, right?, to bind a client to a specific IP. It seems like an unusual, but important, thing to be able to do. I mean, if anything can do it, perl can. . .

Thanks!

******************************
use Socket; my @test=('yahoo.com','whois.networksolutions.com','165.247.62.62'); sub whoislookup2{ my($domain,$server,$ip) = @_; my(@test,$sin); socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or retur +n undef; # This builds the address of the remote machine, to be used in the + connect my $remote_host=inet_aton($server) or return undef; $sin = sockaddr_in(43, $remote_host); # This builds the address of the local machine, to be used for bin +ding the client to a specific IP (this program) my $local_host=inet_aton($ip) or return undef; my $local = sockaddr_in(43, $local_host); bind(SOCK,$local) or print 'Couldn\'t bind to local\n'; connect(SOCK, $sin) or return undef; select((select(SOCK),$| =1)[0]); #This enables buffering on SOCK print SOCK "$domain\n"; @test=<SOCK> or return undef; close(SOCK) or return undef; return @test; }

Replies are listed 'Best First'.
Re: Bind Socket client to specific IP
by Kanji (Parson) on Aug 05, 2001 at 07:19 UTC

    I don't pretend to know the Socket module and you don't clarify whether you're after "more control" of your socket solely for the purpose of binding to an arbitrary IP, but IO::Socket::INET is quite capable of doing so ...

    #!/usr/bin/perl use IO::Socket; use constant DEFAULT_SERVER => "whois.networksolutions.com"; use constant DEFAULT_IP => "0.0.0.0"; # any sub whois { my($domain,$server,$ip) = @_; $server ||= DEFAULT_SERVER; $ip ||= DEFAULT_IP; my $whois = IO::Socket::INET->new( PeerAddr => $server, PeerPort => "whois(43)", Proto => "tcp", LocalAddr => $ip, ); return unless defined $whois; $whois->print( "$domain\r\n" ); return $whois->getlines; } die("Usage: $0 domain [whois server [local ip]]\n") unless @ARGV; print whois(@ARGV);

    If you still need to use Socket instead of IO::Socket::INET, perhaps a peek under the hood of the latter is in order so you can figure out how the above wraps around the lower level stuff.

        --k.


Re: Bind Socket client to specific IP
by kschwab (Vicar) on Aug 05, 2001 at 18:31 UTC
    One thing that jumps out is that you are trying to bind to local port 43. This would require that the script run as root on most unix-like OS's. I'm not aware of any requirement for a whois client to bind to port 43 on the local end of the socket.

    Perhaps you could try changing

    my $local = sockaddr_in(43, $local_host);
    to
    # the '0' lets the kernel pick the next unused port my $local = sockaddr_in(0, $local_host);
    Additionally, checking return values and printing $! on errors might help point you in the right direction. Particularly: bind(SOCK,$local) or die "Can't bind: $!";