17.1. Writing a TCP ClientProblemYou want to connect to a socket on a remote machine. SolutionThis solution assumes you're using the Internet to communicate. For TCP-like communication within a single machine, see Recipe 17.6. Either use the standard (as of 5.004) IO::Socket::INET class: use IO::Socket;
$socket = IO::Socket::INET->new(PeerAddr => $remote_host,
PeerPort => $remote_port,
Proto => "tcp",
Type => SOCK_STREAM)
or die "Couldn't connect to $remote_host:$remote_port : $@\n";
# ... do something with the socket
print $socket "Why don't you call me anymore?\n";
$answer = <$socket>;
# and terminate the connection when we're done
close($socket);or create a socket by hand for better control: use Socket;
# create a socket
socket(TO_SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
# build the address of the remote machine
$internet_addr = inet_aton($remote_host)
or die "Couldn't convert $remote_host into an Internet address: $!\n";
$paddr = sockaddr_in($remote_port, $internet_addr);
# connect
connect(TO_SERVER, $paddr)
or die "Couldn't connect to $remote_host:$remote_port : $!\n";
# ... do something with the socket
print TO_SERVER "Why don't you call me anymore?\n";
# and terminate the connection when we're done
close(TO_SERVER);DiscussionWhile coding this by hand requires a lot of steps, the IO::Socket::INET class wraps them all in a convenient constructor. The important things to know are where you're going (the PeerAddr and PeerPort parameters) and how you're getting there (the Type parameter). IO::Socket::INET tries to determine these things from what you've given it. It deduces Proto from the Type and Port if possible, and assumes PeerAddr is a string containing either a hostname ( If you want a SOCK_STREAM connection to a port on a particular machine with no other options, pass a single string to $client = IO::Socket::INET->new("www.yahoo.com:80")
or die $@;If an error occurs, IO::Socket::INET will return $s = IO::Socket::INET->new(PeerAddr => "Does not Exist",
Peerport => 80,
Type => SOCK_STREAM )
or die $@;If your packets are disappearing into a network void, it can take a while for your inability to connect to a port to be recognized. You can decrease this time by specifying a $s = IO::Socket::INET->new(PeerAddr => "bad.host.com",
PeerPort => 80,
Type => SOCK_STREAM,
Timeout => 5 )
or die $@;If you do this, though, there's no way to tell from INADDR_ANY is a special address, meaning "listen on any interface." If you want to restrict it to a particular IP address, add a $inet_addr = inet_aton("208.146.240.1");
$paddr = sockaddr_in($port, $inet_addr);
bind(SOCKET, $paddr) or die "bind: $!";If you know only the name, do this: $inet_addr = gethostbyname("www.yahoo.com")
or die "Can't resolve www.yahoo.com: $!";
$paddr = sockaddr_in($port, $inet_addr);
bind(SOCKET, $paddr) or die "bind: $!";See AlsoThe
|