Perl UNIX Wizards,

Wanted to summarize what I found on this problem and post the code
below, in the hopes that it helps others.  A special thanks to Steve
Aaron and Simon Wistow for their help. Original question is below the
posted code.

The question originally asked about a data structure for reading
binary data from a socket, so that the message can be interpreted, as
well as individual bytes of the message.

Well I think I found the answer in the form of building a record
through an array data structure.

Here is the function below.  It does the following:
1. Checks to see if the message received from the server has a
"continuity" bit set.  If it does, it loops and continues to read.
2. Reads the first two bytes as the length of the message to be
received.
3. Reads the length of the message from the socket and copies it into
an array, a byte at a time
4.  Take this raw array and copy it into a data structure, a byte at a
time

I am sure there are a thousand ways to improve upon the code, as it is
very messy.  But this is what I have for now.  If there are any
suggestions for improvement, I'll all ears.  Thanks for your help.




sub vcoread {
###
# Declare somes stuff that is really going to help us out
# 
###
$message_num = 0;
$MessageCount = 1;
$bit_check = 8;
while ($bit_check == 8) {

        #######
        # Reading the length of the message, the first two bytes 
        #######
        print ("\nDisplaying Message:\n");

        ### Read first two bytes
        $bytes_read = sysread ($socket, $buf, 2);

        ### Unpack into hex
        $bytes_to_read = unpack ('H4', $buf);

        ### Print it
        print ("bytes_to_read value :$bytes_to_read\n");

        ### Get the second nibble of the byte
        $hexlen = substr $bytes_to_read, 2, 2;

        ### Print it
        print ("broken down to last byte: $hexlen\n");

        ### Get a decimal value for this nibble
        $declen = hex($hexlen);

        ### interpret a Hex length for unpack
        $bytes = H . $declen * 2;

        ### print it
        print ("$bytes\n");

        ###
        # reading the actual message since we know how long it is now
        ###

        ### Read message into $buf
        $messagelen[$message_num] = sysread ($socket, $buf, $declen);
        print("messagelen[$message_num]: $messagelen[$message_num]\n");

        ### Unpack $buf and read into $message1 
        $message1 = unpack ($bytes, $buf);

        ### print $message1
        #print ("message1: $message1\n");

        ### Two characters at a time, read $message1 into @kim
        ### This is reading the message into a raw form, into a basic @kim array
        $count = 0;
        for (my $i = 0; $i < $messagelen[$message_num]; $i++) {
                $kim1[$i] = substr $message1, $count, 2;
                $count = $count + 2;
        }

        #print ("kim1: \n");
        #print ("@kim1\n");



        ####
        # Build the data structure for reading messages
        ###
        my $d = 0;
        $message[$message_num]{nhsegment}{svca} = $kim1[$d];
        $d = $d + 1;
        $message[$message_num]{nhsegment}{dvca} = $kim1[$d];
        $d = $d + 1;
        $message[$message_num]{nhsegment}{ncnt} = $kim1[$d];
        $d = $d + 1;
        $message[$message_num]{nhsegment}{nsta} = $kim1[$d];
        $d = $d + 1;

        $message[$message_num]{msegment}{func} = $kim1[$d];
        $d = $d + 1;
        $message[$message_num]{msegment}{acod} = $kim1[$d];
        $d = $d + 1;
        $message[$message_num]{msegment}{rang}[0] = $kim1[$d];
        $d = $d + 1;
        $message[$message_num]{msegment}{rang}[1] = $kim1[$d];
        $d = $d + 1;
        $message[$message_num]{msegment}{rang}[2] = $kim1[$d];
        $d = $d + 1;
        $message[$message_num]{msegment}{rang}[3] = $kim1[$d];
        $d = $d + 1;

        ### Print the first part of the message, the network header and first
        ### part of message segment
        print ("\n Print the first part of data structure:\n");
        print ("svca: $message[$message_num]{nhsegment}{svca}\n");
        print ("dvca: $message[$message_num]{nhsegment}{dvca}\n");
        print ("ncnt: $message[$message_num]{nhsegment}{ncnt}\n");
        print ("nsta: $message[$message_num]{nhsegment}{nsta}\n");

        print ("func: $message[$message_num]{msegment}{func}\n");
        print ("acod: $message[$message_num]{msegment}{acod}\n");
        print ("rang: $message[$message_num]{msegment}{rang}[0]\n");
        print ("rang: $message[$message_num]{msegment}{rang}[1]\n");
        print ("rang: $message[$message_num]{msegment}{rang}[2]\n");
        print ("rang: $message[$message_num]{msegment}{rang}[3]\n");

        ###
        # A loop that creates the Report elements of the data structure 
        ###

        my $a = $d;
        my $rnumbers = ($messagelen[$message_num] - 10)/8;
        print("\n rnumbers or number of reports: $rnumbers\n");
        my $c = 1;
        $rnumber = "relement" . $c;
        for ( my $b = 0; $b < $rnumbers; $b++) {

                $message[$message_num]{msegment}{$rnumber}{paddress1} = $kim1[$a];
                print ("\n$rnumber: 
$message[$message_num]{msegment}{$rnumber}{paddress1}");
                $a = $a + 1;
                $message[$message_num]{msegment}{$rnumber}{paddress2} = $kim1[$a];
                print ("$message[$message_num]{msegment}{$rnumber}{paddress2}");
                $a = $a + 1;
                $message[$message_num]{msegment}{$rnumber}{paddress3} = $kim1[$a];
                print ("$message[$message_num]{msegment}{$rnumber}{paddress3}");
                $a = $a + 1;
                $message[$message_num]{msegment}{$rnumber}{paddress4} = $kim1[$a];
                print ("$message[$message_num]{msegment}{$rnumber}{paddress4}");
                $a = $a + 1;

                $message[$message_num]{msegment}{$rnumber}{pstate} = $kim1[$a];
                print ("$message[$message_num]{msegment}{$rnumber}{pstate}");
                $a = $a + 1;
                $message[$message_num]{msegment}{$rnumber}{psuppstate} = $kim1[$a];
                print ("$message[$message_num]{msegment}{$rnumber}{psuppstate}");
                $a = $a + 1;
                $message[$message_num]{msegment}{$rnumber}{isdnstate} = $kim1[$a];
                print ("$message[$message_num]{msegment}{$rnumber}{isdnstate}");
                $a = $a + 1;
                $message[$message_num]{msegment}{$rnumber}{isdnsub} = $kim1[$a];
                print ("$message[$message_num]{msegment}{$rnumber}{isdnsub}");
                $a = $a + 1;

                $c = $c + 1;
                $rnumber = "relement" . $c;
        }

        ###
        # Check whether the accesscode C bit is set;
        # Will there be more messages?
        ###

        $bit_check = substr($message[$message_num]{msegment}{acod}, 0, 1);
        ## If $bit_check = 8, then there are more messages to come
        ## for this report
        print("\n MessageCount: $MessageCount; bit_check: $bit_check \n");
        ###
        # Increment only if bit_check says there are more
        ###
        if ( $bit_check == 8 ) {
                $MessageCount = $MessageCount + 1;
        }

# End of while loop
}

#End of vcoread()
}



ORIGINAL QUESTION:
<SNIP>
Hello guys and girls,

I am writing a TCP client program that connects to a server, sends
binary data, and should receive a message back.  The problem I have am
having
is on the receiving end.  I was wondering if any of you have
implemented something like this and may be able to help.

I want the
program to be able to read the socket and, byte by byte, insert data
from the TCP stream into data structure, such as an array, so that
each byte may be referenced later.

Here is the message construction:
################################################
$Len1 = 0x00;
$Len2 = 0x0A;
$SVCA = 0x96;
$DVCA = 0xDF;
$CTRL = 0x40;
$STAT = 0x00;
$FUNCID = 0x83;
$ACCESS = 0x04;
$RGB1 = 0x00;
$RGB2 = 0x00;
$RGB3 = 0x00;
$RGB4 = 0x0A;
#################################################

# Message construction
$bytestring = pack('C*', $Len1, $Len2, $SVCA, $DVCA, $CTRL, $STAT, $FUNCID,
$ACCESS, $RGB1, $RGB2, $RGB3, $RGB4);

print ("Begin now to send message to socket after $waittime seconds\n");
sleep $waittime;
$len = length($bytestring);

#######
# Here is the routine that sends to the socket...Needs work
#######
$offset = 0;
$bytes_to_write = $len - $offset;
$bytes_written  = 0;
while ($bytes_to_write) {
        $bytes_written = syswrite ($socket, $bytestring, $bytes_to_write,
$offset);
        $offset         += $bytes_written;
        $bytes_to_write -= $bytes_written;
        }

#######
# Receiving section
#################

$offset = 0;
$bytes_to_read = length(<$socket>);
while ($bytes_to_read) {
        $bytes_read = sysread ($socket, $bufrcv, $bytes_to_read, $offset);
        $bytes_to_read -= $bytes_read;
        $offset += $bytes_read;

}



Now I can see with TCPDUMP on this Red Hat 7.2 machine that the server
is sending back the message.  I just need to be able to read the
message into a data structure, a byte at a time.

Any help very much appreciated.
-jason

<END SNIP>

_______________________________________________
Perl-Unix-Users mailing list. To unsubscribe go to 
http://listserv.ActiveState.com/mailman/subscribe/perl-unix-users

Reply via email to