http://qs321.pair.com?node_id=764237

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

Hello Mates , can you please Tell what $msg Returns here.
my $maxMsgCodeLength = 15; my $ip= 192.168.106.60; my $port= 9000; sub pStartBEMsg { my ($ip, $port) = @_; my $msgCode = "StartBE"; $msgCode = $msgCode.(" " x ($maxMsgCodeLength-length($msgCode))); my $msg = pack("a".$maxMsgCodeLength."ia*",$msgCode, $port, $ip); return $msg; }
I want to know what pack and Unpack do excatly

Replies are listed 'Best First'.
Re: Please Explain this Function
by binf-jw (Monk) on May 15, 2009 at 13:00 UTC
    The function returns a formated string with 3 components joined with no token together. The components are 'packed' in to a string
    OK so...
    my $msg = pack("a".$maxMsgCodeLength."ia*",$msgCode, $port, $ip);
    "StartBE" is 7 characters long, this gets postfixed with spaces by
      $msgCode = $msgCode.(" " x ($maxMsgCodeLength-length($msgCode))); We'll say the max length is 10 here to make it easier.
    "StartBE   " is now our string.
    my $msg = pack( "a10ia*", $msgCode, $port, $ip );
    Can be written more clearly as
    my $msg = pack( "a20 i a*", $msgCode, $port, $ip );
    From pack on perldoc:
    a = A string with arbitrary binary data, will be null padded.
    i = A signed integer value.

    The three arguments ( $msgCode, $port, $ip ) get 'packed' into ( a10, i and a* ) respectively.

    10 Number of characters in first arugment
    * However many items are left

    If you're familar with printf then it's simlar (but more powerfull then that )
    printf( "%s %d %s", $msgCode, $port, $ip );




    You could use 'A' instead of 'a' in the pack statement. This will pad with spaces hence if you set A20 and only give a string length 10 then 10 spaces are added to the end rendering the line previous to pack useless. You'd probably want to make the function more generic...
    print getMessage ( 'StartBE', $ip, $port ), "\n"; sub getMessage { my ( $msgCode, $ip, $port) = @_; return pack "A10 i A*", $msgCode, $port, $ip; }


    J,
      Thanks a Lot , binf-jw This helps me a lot with your clear explanation
Re: Please Explain this Function
by targetsmart (Curate) on May 15, 2009 at 10:51 UTC
    see pack and perlpacktut

    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.
Re: Please Explain this Function
by johngg (Canon) on May 15, 2009 at 13:17 UTC
    $msgCode = $msgCode.(" " x ($maxMsgCodeLength-length($msgCode)));

    That code pads the string to a set width with spaces. The same could be achieved using sprintf or directly with pack using the 'A' format specifier, which pads a string to a set width with spaces. The 'a' specifier actually used in your code would pad with nulls (ASCII 0) but as the string has already been padded to the necessary width no nulls appear. The 'i' specifier will output a signed integer of at least 4 bytes width and the exact format will be architecture dependant. The following might help you to see what is happening.

    $ perl -e ' > $maxMsgCodeLength = 15; > $port = 9000; > $ip = q{192.168.106.60}; > $msgCode = q{StartBE}; > $msg = pack qq{A${maxMsgCodeLength}ia*}, $msgCode, $port, $ip; > print $msg;' | hexdump -C 00000000 53 74 61 72 74 42 45 20 20 20 20 20 20 20 20 28 |StartBE + (| 00000010 23 00 00 31 39 32 2e 31 36 38 2e 31 30 36 2e 36 |#..192.16 +8.106.6| 00000020 30 |0| 00000021 $

    You can see in this case that the port no of 9000 has been represented by the four hex bytes 28230000 (running under Cygwin on XP). Reversing the process gives:-

    $ perl -le 'print unpack q{i}, qq{\x28\x23\x00\x00};' 9000 $

    I hope this is useful.

    Cheers,

    JohnGG

Re: Please Explain this Function
by apl (Monsignor) on May 15, 2009 at 11:27 UTC
    Why not insert print "msg /".pStartBEMsg( $ip, $port )."/\n"; before the sub?

      msg /StartBE        (#  &#9492;żj</
      (more or less, the └ in the code tags was replaced by its HTML equivalent, &#9492;)

      Not very useful in determining what the pack function is trying to do. It looks like line noise, so did the pack fail? Is the format wrong? I dunno.

      But I'll also mention that pack and unpack still confuse me, even though I know the surrounding Perl syntax in that function. And even after reading most of perldoc -f pack and perldoc perlpacktut.

        You had asked
        can you please Tell what $msg Returns here.

        My point is that you could have found out for yourself what was being returned. Anything else (what does pack/unpack do) is a separate question.