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


My program is such that it first reads the file imp2.txt and stores it in a array.According to the flow of requests and responses it goes to the send block for sending messages or goes to the receive block for receiving the responses from the server. Actually i am using goto for it. But suggest me some more decent way for doing it.
use IO::Socket::INET; use strict; use Config::Tiny; use Config::Random; my ($DATA,$text,$msg, $array1); my @array; open TESTCASE, "imp2.txt" or die $!; while(<TESTCASE>) { $array1 = $_; chomp $array1; $array[$incre]= $array1; $incre++; } open CONFIGFILE, "imp1.txt" or die $!; { local $/; $/ = undef; $DATA=<CONFIGFILE>; } my $Config = Config::ACTI->new(); $Config = Config::ACTI->read_string( $DATA ); $s = $Config->{_}; my $method= <<END; REGISTER sip: 36.212.176.07 SIP/2.0\r Via: SIP/2.0/UDP 36.212.176.90:5060; branch= z9hg4bk340\r To: sanjay<sip:userA@36.212.176.90>\r From:sanjay<sip:userA@36.212.176.90>;tag= abcd1250\r Max-Forwards: 70\r Call-ID: abchjhg1560@36.212.176.90\r CSeq: 1 REGISTER\r Contact:sanjay<sip:userA@36.212.176.90>; expires=7200\r Content-Length:0\r \r END my $MySocket=new IO::Socket::INET->new( LocalAddr=>$s->{Local_IP}, LocalPort=>$s->{LocalPort}, PeerPort=>$s->{RemotePort}, Proto=>$s->{Transport}, PeerAddr=>$s->{Remote_IP} ); $MySocket or die "no socket :$!"; print "\nClient Started: Ready For Packet To Send:\n"; my $incre = 0; COND:for(;;) { last if $array[$incr] eq ''; if ($array[$incr] eq "[SEND]") { $incr++; if ($array[$incr] eq ("REGISTER" || "INVITE" || "ACK" || "BYE" || + "OPTION" || "CANCEL")) { $incr++; goto OUTER; } else { print "Bad Request :$array[$incr]"; exit 1; } } elsif ($array[$incr] eq "[RECV]") { $incr++; if($array[$incr] == (100 || 200 || 300 || 400)) { $incr++; goto INNER; } else { print "Bad Response name:$array[$incr]"; exit 1; } } else { print "Bare word found:"; exit 1; } } OUTER:for(;;) { my $msg=$method; print "\nSending message:$msg"; $MySocket->send($msg); goto COND; } INNER:for(;;) { print "Waiting for Response:\n"; $MySocket->recv ($text,1000);#///Recv print "\nReceived message From:$text"; goto COND; }
The imp1.txt contains
Remote_IP=36.212.176.07
RemotePort=5060
Local_IP=36.212.176.90
LocalPort=5060
Transport=udp
The imp2.txt contains
[SEND] REGISTER [RECV] 100 [RECV] 200

2006-08-30 Retitled by holli, as per Monastery guidelines
Original title: 'plz, suggest me any suitable code for it???'

Edited by planetscape - added readmore tags

( keep:0 edit:15 reap:0 )

Replies are listed 'Best First'.
Re: How to replace 'goto' by another construct?
by Hofmator (Curate) on Aug 30, 2006 at 08:23 UTC
    There are a couple of things that can be improved with your code. I will not address all of them ...
    • Instead of the goto you want subroutines (perlsub).
    • Don't use global variables if they can be avoided.
    • Comparisons like $foo eq ('baz' || 'bar') don't work, use $foo eq 'baz' || $foo eq 'bar' instead.
    • Please consider indenting your code properly, e.g. like perltidy does it.
    • use warnings; can help you uncover bugs in your code.

    To get a bit more concrete, here are some bits and pieces of your code rewritten:

    open TESTCASE, "imp2.txt" or die $!; chomp(@array = <TESTCASE>); open CONFIGFILE, "imp1.txt" or die $!;
    and instead of the goto OUTER (a similar improvement can be made for goto INNER):
    if (...) { $incr++; sendMessage(); } # ... { my $msg = <<END; REGISTER sip: 36.212.176.07 SIP/2.0\r Via: SIP/2.0/UDP 36.212.176.90:5060; branch= z9hg4bk340\r ... END sub sendMessage { print "\nSending message:$msg"; $MySocket->send($msg); } }

    -- Hofmator

    Code written by Hofmator and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: How to replace 'goto' by another construct?
by shmem (Chancellor) on Aug 30, 2006 at 08:17 UTC
    Since you are in a loop, you could replace the goto calls with subroutine calls and next, e.g:
    for(;;) { if ($array[$incr] eq "[SEND]") { if( .. whatever .. ) { $incr++; outer(); next; } } elsif ($array[$incr] eq "[RECV]") { ... $incr++ inner(); next; } } sub outer { my $msg=$method; print "\nSending message:$msg"; $MySocket->send($msg); } sub inner { print "Waiting for Response:\n"; $MySocket->recv ($text,1000);#///Recv print "\nReceived message From:$text"; }

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: How to replace 'goto' by another construct?
by Leviathan (Scribe) on Aug 30, 2006 at 08:15 UTC

    Why not move the body of the labels into where the goto is?

    print "\nClient Started: Ready For Packet To Send:\n"; my $incre = 0; { last if $array[$incr] eq ''; if ($array[$incr] eq "[SEND]") { $incr++; if ($array[$incr] eq ("REGISTER" || "INVITE" || "ACK" || "BYE" || + "OPTION" || "CANCEL")) { $incr++; my $msg=$method; print "\nSending message:$msg"; $MySocket->send($msg); } else { print "Bad Request :$array[$incr]"; exit 1; } } elsif ($array[$incr] eq "[RECV]") { $incr++; if($array[$incr] == (100 || 200 || 300 || 400)) { $incr++; print "Waiting for Response:\n"; $MySocket->recv ($text,1000);#///Recv print "\nReceived message From:$text"; } else { print "Bad Response name:$array[$incr]"; exit 1; } } else { print "Bare word found:"; exit 1; } redo; }

    --
    Leviathan