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

here is the problem...i used komodo IDE to modify the code to function properly, and when i run it on the Windows platform, both in and out of a debugger, it works perfectly returning my values as it should... however, when i put this on a linux machine, it returns this message: "Modbus client : problem with recv:" i have not a clue as to what the problem is... any ideas on what it could be would be appreicated...
#!/usr/bin/perl5.8.7 use IO::Socket; use XML::Simple; use crctable; use strict; use constant MAX_RECV_LEN => 65536; ##################### reading configuration from xml file ############ +##################### my $xmlfile = 'config.xml'; #Configuration file my $xs1 = XML::Simple->new(); my $doc = $xs1->XMLin($xmlfile) or die "Modbus client : problem with congig file: $xmlfile\n"; my $simple_tcp_port = $doc->{SERVER}->{PEERPORT}; my $remote_host = $doc->{SERVER}->{PEERADDR}; my $remote = shift || $remote_host; my $remote_port = shift || $simple_tcp_port; my $slave_add = $doc->{REGISTERS}->{SLAVEADDR}; my $start_add = $doc->{REGISTERS}->{STARTADDR} ; my $quantity = $doc->{REGISTERS}->{QUANTITY}; my $polls_time = $doc->{REGISTERS}->{POLLSTIME}; my $nr_of_polls = $doc->{REGISTERS}->{NROFPOLLS}; my $data_format = $doc->{REGISTERS}->{DATAFORMAT}; my $meas_scale = $doc->{REGISTERS}->{SCALE}; my $hi_limit = $doc->{REGISTERS}->{HILIMIT}; my $lo_limit = $doc->{REGISTERS}->{LOWLIMIT}; my $trans_serv = getprotobyname( 'tcp' ); $remote_host = gethostbyname( $remote ) or die "Modbus client : name lookup failed: $remote\n"; my $destination = sockaddr_in( $remote_port, $remote_host ); my $start_add_val = pack("n",$start_add); my $pack_val = unpack("H*", $start_add_val); my $msg_count = 0; my $pass; $quantity < 256 or die "Nr of registers must be less or equal 255\n"; #################### end of configurations ########################### +################## #################### Modbus frame #################################### +################### my @buffor = (); $buffor[0] = chr($slave_add); $buffor[1] = chr(3); $buffor[2] = chr(hex (substr ($pack_val, 0, 2))); $buffor[3] = chr(hex (substr ($pack_val, 2, 2))); $buffor[4] = chr(0); $buffor[5] = chr($quantity); ##################### end of Modbus frame ############################ +################### ##################### CRC ############################################ +################### my $i; my $index; my $Length = 6; my $crc_Low = 0xFF; my $crc_High = 0xFF; for ($i = 0; $i<$Length; $i++) { our @crc_table; $index = ($crc_High ^ ord($buffor[$i])); $crc_High = $crc_Low ^ $crc_table[$index] ; $crc_Low = $crc_table[$index + 256]; } $buffor[6] = chr($crc_High); $buffor[7] = chr($crc_Low); ##################### end of CRC ##################################### +################### #################### connecting to the server ######################## +################## socket( TCP_SOCK, PF_INET, SOCK_STREAM, $trans_serv ) or die "Modbus client: socket creation failed: $!\n"; my $con_ok = connect( TCP_SOCK, $destination ) or warn "Modbus client: connect to remote system failed: $!\n"; next unless $con_ok; ################### server connected ################################# +################## ################### reading registers ################################ +################## while ( $msg_count < $nr_of_polls){ my $data = join('',@buffor); #Modbus frame to scalar send( TCP_SOCK, $data, 0 ) or warn "Modbus client : problem with send: $!\n"; my $from_who = recv( TCP_SOCK, $data, MAX_RECV_LEN, 0 ); if ( $from_who ){ #New dat +a from server my ( $the_port, $the_ip ) = sockaddr_in( $destination ); my $i; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = + localtime(time); print "\n $hour:$min:$sec >> New data from Modbus RTU de +vice \n"; for ($i = 0; $i < (length( $data ) - 5)/4; $i++){ my $hex = substr $data, $i*2+3, 4; if ($data_format eq "HEX"){ $hex = unpack ("H*", $hex); $hex = unpack "f", reverse pack "H*", $hex ; } else { $hex = unpack "n", $hex; } my $regadd = 1 + $start_add + $i; print " Register $regadd : "; printf("%.3f", $hex); pr +int " $meas_scale \n"; if($lo_limit > $hex ){ print "Warning limit is below low limit cr +iteria!\n" }elsif($hi_limit < $hex){ print "Warning limit is above High Limit C +riteria!\n" } } #my $f = 0x42700000; #my $reg_value = unpack("f", pack("i", $f)); #printf("%.3f", $reg_value); } else { warn "Modbus client : problem with recv: $!\n"; } } continue { $msg_count++; sleep($polls_time); } close TCP_SOCK or warn "tcp_c1: close failed: $!\n";

Replies are listed 'Best First'.
Re: Problem with recv()???
by Corion (Patriarch) on Apr 22, 2008 at 17:14 UTC

    You get that error message, because of this line:

    warn "Modbus client : problem with recv: $!\n";

    Your code is far too large and badly indented, so I won't bother to track down to which if the else belongs. I guess it belongs to the following lines:

    my $from_who = recv( TCP_SOCK, $data, MAX_RECV_LEN, 0 ); if ( $from_who ){

    So, you didn't receive anything, or just a bare 0. I don't know what you're actually sending over the wire. Maybe consider printing that out.

    Also, I'm not sure whether send and recv make sense for TCP (stream) connections - I'd use normal read and print.

    As you claim that your program works on Windows but not on Linux, maybe you also have a problem with differences in how the two OSes buffer things, or not...

Re: Problem with recv()???
by pc88mxer (Vicar) on Apr 22, 2008 at 17:37 UTC
    After reading the documentation for recv, the check on $from_who really should be:
    if (defined($from_who)) { # message received } else { # error }
    See if that makes a difference.