Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Neebie, packet fragment? 1

Status
Not open for further replies.

ldavies

Programmer
Joined
Dec 8, 2006
Messages
1
Location
GB
Hi There,

I'm a C programmer, new to perl.

I'm a little disoriented with the shear number of functions available.

I want to use a perl script to break up the following packet into it's individual components:

<Address (2 digit hex)><Command (1 digit hex)><Length (2 digit hex)><data (Length bytes>

Typical Packet:
01A05hello

Where:
Address 1
Command A
Length 5
Data hello

Also, the script input may contain a number of the packets e.g. <packet 0><packet 1><packet2>

Is there a whiz bang function that can break up these packets into the individual components?

Many thanks,

Lee
 
you could use a regular expression:

Code:
my ($address, $command, $length, $data) = $packet =~ /(..)(.)(..)(.*)/;

breaking up a number of them would depend on how they are formatted whn grouped together. If there is some type of a delimiter, such as a space between each packet, that would be easy. If not, there would have to be some way of distinguishing where one packet ends and another begins.

- Kevin, perl coder unexceptional!
 
As an alternative, unpack is ideally suited to this:
Code:
my ($address, $command, $length, $data) = unpack( 'A2A1A2A*', $packet );
 
Unpack also seems to have a template character / which allows it to parse data like yours correctly, where you have length/string. When you use this, it doesn't return the length, presumably because you have the string and can find the length anyway. It seems to support repeating groups, so
Code:
my @packets = unpack('(A2A1A2/A)*', $stream);
might split them all out. You'd then have an array of triplets (adr, cmd, data, adr, cmd, data, adr...) which you could process fairly easily.

Haven't tried it, so this is all theoretical... [smile]

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::PerlDesignPatterns)[/small]
 
Trying out everyone's solution:

Code:
my @cmds = qw(01A05hello 4FB06foobar AAC03baz);

foreach my $packet (@cmds) {
	print "$packet (Packet)\n";
	my @data = unpack( 'A2A1A2A*', $packet );
	print "\t@data (Simple, ishnid)\n";
	
	my @data2 = unpack('A2A1A2/A', $packet);
	print "\t@data2 (Template, stevexff)\n";
}

my $group = join '', @cmds;
print "Group Packet = $group (stevexff)\n";
my @alldata = unpack('(A2A1A2/A)*', $group);
while (my @data = splice @alldata, 0, 3) {
	print "\t@data\n";
}

And the results
Code:
C:\bin>perl unpack.pl
01A05hello (Packet)
        01 A 05 hello (Simple, ishnid)
        01 A hello (Template, stevexff)
4FB06foobar (Packet)
        4F B 06 foobar (Simple, ishnid)
        4F B foobar (Template, stevexff)
AAC03baz (Packet)
        AA C 03 baz (Simple, ishnid)
        AA C baz (Template, stevexff)
Group Packet = 01A05hello4FB06foobarAAC03baz (stevexff)
        01 A hello
        4F B foobar
        AA C baz

And the winner of the star is .... stevexff! [party]

Thank you to our sponsors, participants, and audience. And thank you Idavies for the question.

And an honorable mention for Kevin for loving regex's o-so much. They're great.
 
I so rarely remember about unpack for some reason. It really is the right tool for this type of thing.

- Kevin, perl coder unexceptional!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top