#!/usr/bin/perl # for debugging, use .../perl -d ############################################################################## # # TCP/IP server: # - Listen to client # - Fork a child to perform communication # - Child will execute whatever is received as a Unix command # - Go back and listen for more clients # # Usage: TCPserver portNumber & (always run server in the background) # ############################################################################## use Socket; # import Socket.pm $serverPort = $ARGV[0] || 8467; # if none, use port 8467 &setConnect(); # setup connection &clientListen(); # listen to client(s) ############################################################################## # setConnect: Establish connection to listening port ############################################################################## sub setConnect { ### Server information ### my $serverName = `hostname`; #cmd `hostname` chomp($serverName); my $serverAddrBin = gethostbyname($serverName); my @serverAddrNum = unpack("C4", $serverAddrBin); my $serverAddr = join('.', @serverAddrNum); # my $serverAddr = inet_ntoa($serverAddrBin); #same as prev 2 lines print "Server name: $serverName \n"; print "IP address : $serverAddr \n"; print "Port number: $serverPort \n\n"; my $protocol = getprotobyname("tcp"); # my $serverSocket = pack_sockaddr_in($serverPort, undef); my $serverSocket = pack_sockaddr_in($serverPort, INADDR_ANY); ### create socket filehandle ### socket(LISTENSOCKET, PF_INET, SOCK_STREAM, $protocol) || die "$0: Cannot create $protocol socket- $!"; ### set socket options ### setsockopt(LISTENSOCKET, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die "$0: Cannot set socket options- $!"; ### bind socket to local port number ### bind(LISTENSOCKET, $serverSocket) || die "$0: Cannot bind socket to server- $!"; ### Establish the length of the waiting queue ### listen(LISTENSOCKET, SOMAXCONN) || die "$0: Cannot establish listening queue- $!"; } ############################################################################## # clientListen: listen to clients on generic socket, # when a new client arrives --> fork a child to serve him ############################################################################## sub clientListen { select LISTENSOCKET; $| = 1; # set LISTENSOCKET to unbuffered select CLIENTSOCKET; $| = 1; # set CLIENTSOCKET to unbuffered select STDOUT; $| = 1; # set STDOUT to unbuffered for ($connect = 1; ; $connect++) { # loop infinitely print("Listening for connection $connect.....\n\n"); ### accept socket connection from client ### ($clientSocket = accept(CLIENTSOCKET, LISTENSOCKET) ) || die "$0: Cannot accept client connection- $!"; $pid = fork(); # fork a new process (dupl this pgm) defined $pid || die "$0: $!"; # pid == null? then die if ($pid == 0) { &child(); # perform reading from the socket } } } ############################################################################## # child: I'm the child, read from the socket, and write to STDOUT # do whatever the child wants # write results into the socket, and write to STDOUT ############################################################################## sub child { my ($clientPort, $clientAddrBin) = unpack_sockaddr_in($clientSocket); my $clientName = gethostbyaddr($clientAddrBin, AF_INET); my @clientAddrNum = unpack("C4", $clientAddrBin); my $clientAddr = join('.', @clientAddrNum); # my $clientAddr = inet_ntoa($clientAddrBin); #same as prev 2 lines print "Connect to : $clientName \n"; print "at IP addr : $clientAddr \n"; print "Port number: $clientPort \n\n"; while ($data = ) { # read from client socket print STDOUT $data; # print what's received locally # $data =~ tr/[a-z]/[A-Z]/; # translate to upcase (or whatever) $result = `$data`; # execute whatever is requested print CLIENTSOCKET $result; # write back into socket print STDOUT $result; # print what's sent back locally } close(CLIENTSOCKET); exit (0); }