Link to home
Start Free TrialLog in
Avatar of monish
monish

asked on

Perl Socket Problem

I want to be able to change my passwd on the server "ebs2.eecs" from my machine "ebs1.eecs" using sockets.
ebs2.eecs has an entry for the program under /etc/services and /etc/inetd.conf. On calling the program from ebs1.eecs I do get Testing.. as the output but nothing further happens.

1) What do I need to do to get this to work?
2) How come I don't get an output for $name when I call the
   client prog. with an output?

The client program that runs on my machine "ebs1.eecs"

#!/usr/sww/bin/perl
# passwd.client

$AF_INET = 2;
$SOCK_STREAM = 1;
$sockaddr = 'S n a4 x8';

chop ($user = `whoami`) unless $user;

$port = 1997;
$host = 'ebs2.eecs';

($n, $a, $proto) = getprotobyname('tcp');
($n, $a, $t, $l, @thisaddr) = gethostbyname('localhost');
($n, $a, $t, $l, @thataddr) = gethostbyname($host);

$this = pack($sockaddr, $AF_INET, 0, $thisaddr);
$that = pack($sockaddr, $AF_INET, $port, @thataddr);

socket(S, $AF_INET, $SOCK_STREAM, $proto) || die "Can't open socket!\n";
bind(S, $this) || die "Couldn't bind a new socket!\n";
connect(S, $that) || die "Couldn't connect to host $host, port $port!\n";

select(S); $| = 1; select(STDOUT);

print S "$user\n";  ##Pass the user to the server                                  passwd.answerd prog

while (<S>) {
    print;
}

---------------------------------
The server prog on "ebs2.eecs"
---------------------------------

#!/usr/sww/bin/perl
# passwd.server

$ENV{'PATH'} = '/bin:/etc:/etc/bin:/usr/bin:/usr/ucb:/usr/local/bin';
print "Testing.. \n" ;
local($name) = @_ ;

$AF_INET = 2;
$SOCK_STREAM = 1;
$sockaddr = 'S n a4 x8';

$port = 1997;

($n, $a, $t, $l, @thisaddr) = gethostbyname($host);
($n, $a, $proto) = getprotobyname('tcp');
$thisport = pack($sockaddr,$AF_INET,$port,$thisaddr);
socket(S, $AF_INET, $SOCK_STREAM, $proto) || die "Can't open socket!";
bind(S,$thisport) || die "Cannot bind socket \n" ;
listen(S,5) || die "Cannot listen socket \n" ;
for(;;)
{
  accept(NS,S) || die "Cannot accept socket\n" ;
  system "/bin/passwd" ;
  close NS;
}



ASKER CERTIFIED SOLUTION
Avatar of icculus
icculus

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of monish
monish

ASKER

I tried your example. I see the server process start up at
the server "ebs2" and get some error checking output on "ebs1".  
The following is the output I get back on ebs1 when I run the program :

CHECK C1
CHECK C2
CHECK C3
CHECK S1
CHECK C3
CHECK S2
CHECK C3
CHECK S3
bind: Address already in useCHECK C4

So it never goes pass the following line on the server :
bind(Server, $port)                     or die "bind: $!" ;

Any clues on how I can get the client and Server to talk and fix this ? Thanks.


===============================================================
The client code on ebs1 :

#!/usr/local/bin/perl5
require 5.002;
use strict;
use Socket;
use Fcntl;
use POSIX;

my $user = `whoami` ;
my ($remote,$port,$iaddr,$paddr,$proto,$line);

$remote = "ebs2.eecs.berkeley.edu";
$port = 1995 ;

$iaddr = inet_aton($remote) or print "ERROR1\n" ;
$paddr = sockaddr_in($port, $iaddr);

# Open the socket
$proto = getprotobyname('tcp') ;
socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die "Could'nt create socket";

# Call up the server
connect(SOCK, $paddr) or die "Couldn't connect socket";

print "CHECK C1\n" ;
##select(SOCK); $| = 1; select(STDOUT);
print "CHECK C2\n" ;

while(<SOCK>)
{
    print "CHECK C3\n" ;
    print ;
}
print "CHECK C4\n" ;
close (SOCK) || die "Couldn't close socket\n";
exit ;

====================================================
The server code on ebs2 :

#!/usr/local/bin/perl5
require 5.002;
use strict;
use Socket;
use Carp;
use Fcntl;
use POSIX;

print "CHECK S1\n" ;
my $port = 1995;
my $proto = getprotobyname('tcp');

socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!" ;
print "CHECK S2\n" ;
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("1",1))       or die "setsockopt: $!";
print "CHECK S3\n" ;
#bind(Server,sockaddr_in($port,INADDR_ANY)) or print "bind: $!" ;
bind(Server, $port)                     or die "bind: $!" ;
print "CHECK S4\n" ;
listen(Server,SOMAXCONN)                or die "listen: $!" ;

my $paddr;
for ( ; $paddr = accept(Client,Server); close Client)
{
  my($port, $iaddr) = sockaddr_in($paddr);
  my $name = gethostbyaddr($iaddr,AF_INET);
  print Client "Hello there, $name \n";
}

=========================================================








Ok, the bind: Address already in use indicates that either
the port you are using is already bound by another program,
or it is bound by the current program but has not been.

For example, if you run the program and then kill it, the
port will remain bound for a few minutes. I have this problem
with a proxy server I use, it takes about 5 full minutes
before I can run it again after the server dies. Give it
some time and then try again. I know this sucks and is quite
a hassle when debugging but it happens... *sigh*

-Andy