Question

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();
Was it helpful?

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.

OTHER TIPS

You need to import getaddrinfo() from Socket. See the docs.

use Socket 'getaddrinfo';

You might want to use the Sys::Hostname instead of `hostname` on Linux systems. No need to fork for that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top