Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Writing a simple TCP server and connection handling

by tweetiepooh (Hermit)
on Apr 30, 2012 at 10:54 UTC ( #968036=perlquestion: print w/replies, xml ) Need Help??
tweetiepooh has asked for the wisdom of the Perl Monks concerning the following question:

Here is the scenario. I need to write some code that will act like a bridge receiving data via TCP connection and sending SNMP traps on. I don't have any control of the client and at some point will loose connection to the server computer so the code needs to be robust and self repairing. Here is how it should work

The client connects to server (port 1066 so doesn't need to run as root). Every so often it will send some data of the form

chr(1) + message type + data

If message type is "0" (zero) this is a poll message and the data is 4 bytes indicating the number of messages since last poll. The server will reply back in kind with the number of messages since last poll.

If message type is anything else then the data is between 30 and 200 odd bytes terminated with <CRLF>.

Now I have the basics here already. (The specs said the poll was also <CRFL> terminated but it isn't.) There are a couple of concerns and "requirements" that I need some guidance on.

  • the client shows connection is dropped should be kept up - this doesn't seem important but would be nice
  • If no poll is received in 3 mins send SNMP trap - this is a modification of current situation, the trap sent on processing poll should send trap to clear a "poll missed" message
  • need to ensure that if client is disconnected for whatever reason then it can reconnect again

I run the Perl script inside a shell wrapper that will restart the Perl should it terminate. This wrapper also ensures that the environment is set correctly.

<set up bits including point to database and other stuff> my $poll = 0; my $messages = 0; # make the socket my $socket = IO::Socket::INET->new( LocalHost => '<hostname>', LocalPort => 1066, Proto => 'tcp', Listen => 5, Reuse => 1, ) or die "Socket could not be created : $!"; # accept connections while (my $new_sock = $socket->accept()) { while (1) { say "Waiting!"; my $buf=""; # loop until start of message control (chr(1)) while (read($new_sock,$buf,1)) { last if $buf eq chr(1 +);} read($new_sock,$buf,1); if ($buf eq "0") { # handle the POLL message # byte 1 = ASCII start of header (1) # byte 2 = '0' - poll message ID # byte 3 = number of messages since last poll +- 4 bytes # following don't seem to be sent. # byte 7 = ASCII CR (13) # byte 8 = ASCII LF (10) # already have initial bytes now get payload read($new_sock,$poll,4); say "POLL : $poll"; SendPollReply($new_sock); SendSNMP("0","0","--",undef,undef); } else { # Other messages look like they are Cr/LF term +inated $buf .= <$new_sock>; $messages++; say "Buffer : $buf Poll : $poll Messages : +$messages"; # only send traps for message group "A" or "C" if ($buf =~ /([AC])(.{8})((\+\+|--))(\d{8})(.{ +10})/msx) { my $message_group = $1; my $station_code = $2; my $change_type = $3; my $date_time = $5; my $point_name = $6; SendSNMP($message_group,$station_code, +$change_type,$date_time,$point_name); } } } } close($socket); sub SendPollReply { my $new_sock = shift; # send the poll reply # byte 1 = ASCII start of header chr(1) # byte 2 = '0' - response message ID # byte 3 = number of messages since last poll - 4 bytes # byte 7 = Error status '0' if OK # byte 8 = ASCII CR (13) # byte 9 = ASCII LF (10) SendMessage( $new_sock,"0".sprintf("%04d",$messages)."0"); $messages=0; } # wrap message back to poller in required start/end characters sub SendMessage { my ($new_sock,$message) = @_; $message = chr(1).$message.chr(13).chr(10); say "REPLY : $message"; print $new_sock $message; }

Replies are listed 'Best First'.
Re: Writing a simple TCP server and connection handling
by zentara (Archbishop) on Apr 30, 2012 at 14:44 UTC
Re: Writing a simple TCP server and connection handling
by Anonymous Monk on Apr 30, 2012 at 11:59 UTC
    What's the question?
Re: Writing a simple TCP server and connection handling
by Anonymous Monk on Apr 30, 2012 at 13:53 UTC
    Net::Server ... If your quest does not begin and end with then you are probably wasting more time than you realize. No matter what you are doing, it has been done before ... especially the "plumbing bits that everybody has to do."

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://968036]
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2017-11-20 10:02 GMT
Find Nodes?
    Voting Booth?
    In order to be able to say "I know Perl", you must have:

    Results (286 votes). Check out past polls.