Search code examples
perlsocketstcpdnshostname

IO::Socket vs Socket do I "use" both?


I am writing a small program for a networking class I have and ran into a little confusion.

I have things working currently but am seeing some inconsistencies among perl networking examples I find.

Some people import the Socket module, while some import the IO::Socket module. Even more confusing, some import both Socket and IO::Socket.

Is there a point? I thought IO::Socket would import Socket?

I ask because I am trying to use a function "getaddrinfo()" and it keeps yelling at my about "Undefined subroutine &main::getaddrinfo called at ./tcp_server.pl line 13." Which is in the Socket perldoc.

I got it working by manually specifying the host IP... but I want it to automatically retrieve the host IP of the machine it is running on. Any advice?

Here is my code:

#!/usr/bin/perl

# Flushing to STDOUT after each write
$| = 1;

use warnings;
use strict;
use Socket;
use IO::Socket::INET;


# Server side information
# Works with IPv4 addresses on the same domain
my ($err, @res)  = getaddrinfo(`hostname`); #'128.101.38.191';
my $listen_port  = '7070';
my $protocal     = 'tcp';
my ($socket, $client_socket);
my ($client_address, $client_port);
# Data initializer
my $data = undef;


# Creating interface
$socket = IO::Socket::INET->new (
LocalHost   => shift @res,
LocalPort   => $listen_port,
Proto       => $protocal,
Listen      => 5,
Reuse       => 1,
) or die "Socket could not be created, failed with error: $!\n"; # Prints error code

print    "Socket created using host: @res \n";
print    "Waiting for client connection on port $listen_port\n";

while(1) {
    # Infinite loop to accept a new connection
    $client_socket = $socket->accept()
        or die "accept error code: $!\n";

# Retrieve client information
$client_address = $client_socket->peerhost();
$client_port    = $client_socket->peerport();

print "Client accepted: $client_address, $client_port\n";

# Write
$data = "Data from Server";
print $client_socket "$data\n";

# Read
$data = <$client_socket>;
print "Received from client: $data\n";

}
$socket->close();

Solution

  • It's much easier to only use IO::Socket:

    use strict;
    use warnings;
    use IO::Socket::INET;
    my $server = IO::Socket::INET->new(
        LocalPort => 7080,
        Listen => 10,
        Reuse => 1
    ) or die $!;
    while (1) {
        my $client = $server->accept or next;
        print $client "foo\n";
    }
    

    And if you want to do IPv6 just replace IO::Socket::INET with IO::Socket::IP or IO::Socket::INET6. And if you later want to use SSL on the socket replace it with IO::Socket::SSL and add some certificates. It's a bit overhead but a lot less writing of code and much easier to understand.