start page | rating of books | rating of authors | reviews | copyrights

Perl Cookbook

Perl CookbookSearch this book
Previous: 17.0. Introduction Chapter 17
Sockets
Next: 17.2. Writing a TCP Server
 

17.1. Writing a TCP Client

Problem

You want to connect to a socket on a remote machine.

Solution

This 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);

Discussion

While 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 tcp otherwise.

PeerAddr is a string containing either a hostname ( "www.oreilly.com" ) or an IP address ( "204.148.40.9" ). PeerPort is an integer, the port number to connect to. You can embed the port number in the address by giving an address like "www.oreilly.com:80" . Type is the kind of socket to create: SOCK_DGRAM for datagrams, or SOCK_STREAM for streams.

If you want a SOCK_STREAM connection to a port on a particular machine with no other options, pass a single string to IO::Socket::INET->new consisting of the hostname and port separated by a colon:

$client = IO::Socket::INET->new("www.yahoo.com:80")     or die $@;

If an error occurs, IO::Socket::INET will return undef and $@ ( not $! ) will be set to the error message.

$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 Timeout parameter to IO::Socket::INET->new() :

$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 $! or $@ whether you couldn't connect or whether you timed out. Sometimes it's better to set it up by hand instead of using a module.

INADDR_ANY is a special address, meaning "listen on any interface." If you want to restrict it to a particular IP address, add a LocalAddr parameter to your call to IO::Socket::INET->new. If coding by hand code, do this:

$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 Also

The socket , bind , connect , and gethostbyname functions in Chapter 3 of Programming Perl and in perlfunc (1); the documentation for the standard Socket, IO::Socket, and Net::hostent modules; the section on "Internet TCP Clients and Servers" in Chapter 6 of Programming Perl and in perlipc (1); Unix Network Programming , by W. Richard Stevens, published by Prentice Hall (1992); Recipe 17.2 ; Recipe 17.3


Previous: 17.0. Introduction Perl Cookbook Next: 17.2. Writing a TCP Server
17.0. Introduction Book Index 17.2. Writing a TCP Server