aodukoya has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to program a client-server utility. which on the client checks the code entered and does some checks against an oracle database if the user so desires. My stand alone script works perfectly well on a local system. But I want to be able to check the data against other databases on the network: The problem is I am able to issue and confirm one command alone any other thing that I try and the script hangs...
I have tried using the non blocking code but this had no effect
i) Stand alone output
$ ./tester -local + Starting up the test util in single user mode ... + TestUtil>qry chk table testa + TESTA .............................Table Exists(ok) + TestUtil>qry chk table testb + TESTB .............................Table Exists(ok) + TestUtil>dml upd table testb + The where clause on testb is based on where object_id equals, please g +ive a valid value: 90 UpdTab> The sql is update testb set object_name = 'Shareplex' where ob +ject_id = ? The value entered is 90 + The number of rows Updated from testb is 1 + TestUtil>qry chk data testb + The total number of rows for testb is 82 + The number of modified rows are 2 + TestUtil> TestUtil>quit

ii) With network enabled
$ ./tester -local Starting up the test util with network enabled... TestUtil>ddl drp table testa I have received your message[server]-THISISTHEEND DATA in $data slice 1 is THISISTHEEND I have received your message[server]-THISISTHEEND DATA in $data slice 1 is THISISTHEEND TestUtil>ddl create table testa <-it hangs and I have to ctrl+C out

I created a little code to try to reproduce What I want to try to do as the whole code can't be posted, but this reflects the error perfectly well.
Also I noticed if I hash out the section on the client that tries to receive the message from the source all works well.
Client Code-Example
#!/usr/bin/perl + use warnings; use strict; use IO::Socket qw(:DEFAULT :crlf); my $port = $ENV{CM_PORT} || 3013 ; my $host = $ENV{CM_HOSTS} || 'uksupu02' ; my $read ; my $quit ; my $utilprmpt = 'Testing> '; my $socket ; my $user_input = 'start' ; RERUN_PROMPT: while ( $user_input ne 'quit') { + print "$utilprmpt"; + chomp ( $user_input = <>); + if (!$user_input){next RERUN_PROMPT } ; if ($user_input =~/^\s+$/){ next RERUN_PROMPT } ; if ( $user_input eq 'quit') { exit }; &CreateClient ; + } + + sub CreateClient { + $socket = IO::Socket::INET->new("$host:$port") or die "can't create s +ocket: $!"; user_to_host ($socket, $user_input) ; + &host_to_user ($socket); + } + sub user_to_host { + my $sock = shift; + my $msg = shift ; + print $sock $msg ,CRLF; + } + sub host_to_user { + my $sock = shift ; + my $nread ; + my $inp ; + $/ = CRLF ; + while (<$sock>) { + chomp; + my @data = split/-/, $_ ; + print $_ , "\n"; + if ($data[1] eq 'THISISTHEEND') { + return ; + } + } + }

iii) Server code
#!/usr/bin/perl + use warnings; use strict; use IO::Socket qw(:DEFAULT :crlf) ; my $port = $ENV{CM_PORT} || 3013 ; + my $quit = 0 ; my $session ; my $sock ; $SIG{INT} = sub { $quit++ } ; sub server { $sock = IO::Socket::INET->new( Listen => 5, LocalPort => + $port, Timeout => 60*60, Reuse => 1 ) or die "Can't create li +stening socket: $!\n"; warn "Waiting for incoming connections on port $port...\n"; + } &server ; + while ( !$quit ) { + next unless $session = $sock->accept; my $pport = $session->peerport; my $paddr = $session->peeraddr; my $pname = gethostbyaddr($paddr, AF_INET); my $peer = "$pname:$pport" ; warn "Connection from [$peer]\n"; while (<$session>){ chomp; my $msg_recv = $_ ; my $msg_out = ("I have received your message[server]-THISIS +THEEND") . CRLF ; print $session $msg_out ; print " Received=> $msg_recv \n"; } + warn "Connection from [$peer] finished\n"; close $session ; + }

Edited by theorbtwo: Moved from a reply to New user scratch pad. to a root SoPW.

Replies are listed 'Best First'.
Re: Client-Server Programme hangs...
by Errto (Vicar) on Dec 31, 2004 at 00:53 UTC
    I notice a few issues here: First of all, the sample output you gave us could not possibly be produced by the code you've showed us because it includes lines like DATA in $data slice 1 is THISISTHEEND which doesn't appear in your code. Second, in your current code you are creating a new socket for every input from the user. I'm not sure if this is what you want or not. The problem is, you never close these sockets. So here's the sequence that happens right now:
    1. Client receives a message from the usr
    2. Client opens socket with server
    3. Server accepts connection and begins listening for client data
    4. Client sends data and loops, waiting for response from server
    5. Server receives data and writes back to client with the word THISISTHEEND
    6. Client receives this message and ends the loop
    7. Client receives next input from the user
    8. Client opens new socket with the server
    This socket will never be accepted because the client never closed the old one, and the server is still waiting for data on it.
      The Sample output I gave was my initial script the one I posted was to reproduce the same issue with a smaller code, as the other code ran to about 4000 or more lines with some dbi connections and queries against the database.
      Why I am creating a new socket with every command entered by the user is also because I could not get the script to work with just one connection...as I explained above the main script does the following
      1. accept a users command
      2. parse the users command to see if the syntax is correct
      3. connect to a local oracle database and execute the relevant sql with regards to the command entered by the user
      4. go to a server that should have similar data based on an already defined hostname, oracle sid, username and password and check whether the same data is there
      5. report back to the user on the local host the results
      6. User now gets the prompt back and can enter new commands if wanted

      I have tried to put $socket->close ; in a varied number of places especially in the function that creates client connections but I am sure this did not fix the issue. I will test this out again and post my findings.
      Thanks for the tip.
        One other thing. Make sure you put $socket->autoflush() immediately after you create the socket at the client side, and $session->autoflush() immediately after you accept the connection on the server side. In your current code the proper place to do a $socket->close() would be after the return from host_to_user.