0

I'm trying to create a small program that will log information output from a device via TCP

Basically this just streams data out, that i want to capture, and dump into a database for dealing with later

but the device reboots so i need to be able to reconnect when the socket closes with out any human interference

so this is what i have so far

import socket, time, logging, sys, smtplib # Import socket module
logging.basicConfig(filename='Tcplogger.log',level=logging.DEBUG,format='%(asctime)s : %(levelname)s : %(message)s')
logging.info('|--------------------------------------|')
logging.info('|--------------- TCP Logger Starting---|')
logging.info('|--------------------------------------|')
host = '127.0.0.01' # host or Ip address
port = 12345 # output port
retrytime = 1 # reconnect time 
reconnectattemps = 10 # Number of time to try and reconnect 
class TPCLogger:
 def __init__(self):
 logging.debug('****Trying connection****')
 print('****Trying connection****')
 self.initConnection()
def initConnection(self):
 s = socket.socket()
 try:
 s.connect((host, port))
 logging.debug('****Connected****')
 except IOError as e:
 while 1: 
 reconnectcount = 0;
 logging.error(format(e.errno)+' : '+format(e.strerror))
 while 1:
 reconnectcount = reconnectcount + 1
 logging.error('Retrying connection to Mitel attempt : '+str(reconnectcount)) 
 try:
 s.connect((host, port)) 
 connected = True
 logging.debug('****Connected****')
 except IOError as e:
 connected = False
 logging.error(format(e.errno)+' : '+format(e.strerror))
 if reconnectcount == reconnectattemps:
 logging.error('******####### Max Reconnect attempts reached logger will Terminate ######******') 
 sys.exit("could Not connect")
 time.sleep(retrytime)
 if connected == True:
 break
 break 
 while 1:
 s.recv(1034)
LOGGER= TCPLogger()

Which all works fine on start up if a try to connect and its not there it will retry the amount of times set by reconnectattemps

but he is my issue

 while 1:
 s.recv(1034)

when this fails i want to try to reconnect i could of course type out or just copy my connection part again but what i want to be able todo is call a function that will handle the connection and retry and hand me back the connection object

for example like this

class tcpclient
#set some var
host, port etc....
def initconnection:
 connect to socket and retry if needed
 RETURN SOCKET
def dealwithdata:
 initconnection()
 while 1:
 try:
 s.recv
 do stuff here copy to db
 except:
 log error
 initconnection()

I think this is possible but im really not geting how the class/method system works in python so i think im missing something here

FYI just in case you didn't notice iv very new to python. any other comments on what i already have are welcome too :)

Thanks Aj

asked Jul 31, 2013 at 6:49

2 Answers 2

2

Recommendation

For this use-case I would recommend something higher-level than sockets. Why? Controlling all these exceptions and errors for yourself can be irritating when you just want to retrieve or send data and maintain connection.

Of course you can achieve what you want with your plain solution, but you mess with code a bit more, methinks. Anyway it'll look similarly to class amustafa wrote, with handling socket errors to close/reconnect method, etc.

Example

I made some example for easier solution using asyncore module:

import asyncore
import socket
from time import sleep
class Client(asyncore.dispatcher_with_send):
 def __init__(self, host, port, tries_max=5, tries_delay=2):
 asyncore.dispatcher.__init__(self)
 self.host, self.port = host, port
 self.tries_max = tries_max
 self.tries_done = 0
 self.tries_delay = tries_delay
 self.end = False # Flag that indicates whether socket should reconnect or quit.
 self.out_buffer = '' # Buffer for sending.
 self.reconnect() # Initial connection.
 def reconnect(self):
 if self.tries_done == self.tries_max:
 self.end = True
 return
 print 'Trying connecting in {} sec...'.format(self.tries_delay)
 sleep(self.tries_delay)
 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
 try:
 self.connect((self.host, self.port))
 except socket.error:
 pass
 if not self.connected:
 self.tries_done += 1
 print 'Could not connect for {} time(s).'.format(self.tries_done)
 def handle_connect(self):
 self.tries_done = 0
 print 'We connected and can get the stuff done!'
 def handle_read(self):
 data = self.recv(1024)
 if not data:
 return
 # Check for terminator. Can be any action instead of this clause.
 if 'END' in data:
 self.end = True # Everything went good. Shutdown.
 else:
 print data # Store to DB or other thing.
 def handle_close(self):
 print 'Connection closed.'
 self.close()
 if not self.end:
 self.reconnect()
Client('localhost', 6666)
asyncore.loop(timeout=1)

reconnnect() method is somehow core of your case - it's called when connection is needed to be made: when class initializes or connection brokes. handle_read() operates any recieved data, here you log it or something. You can even send data using buffer (self.out_buffer += 'message'), which will remain untouched after reconnection, so class will resume sending when connected again. Setting self.end to True will inform class to quit when possible.

asyncore takes care of exceptions and calls handle_close() when such events occur, which is convenient way of dealing with connection failures.

answered Aug 6, 2013 at 23:05
Sign up to request clarification or add additional context in comments.

2 Comments

What is self.connected in the snippet above?
@TomaszPlonka It is a property of asyncore.dispatcher class, which says whether socket is connected to some endpoint. When execution of self.connect((self.host, self.port)) completes this property is updated - if some error occurred self.connected = False and else True.
1

You should look at the python documentation to understand how classes and methods work. The biggest difference between python methods and methods in most other languages is the addition of the "self" tag. The self represents the instance that a method is called against and is automatically fed in by the python system. So:

class TCPClient():
 def __init__(self, host, port, retryAttempts=10 ):
 #this is the constructor that takes in host and port. retryAttempts is given 
 # a default value but can also be fed in.
 self.host = host
 self.port = port
 self.retryAttempts = retryAttempts
 self.socket = None
 def connect(self, attempt=0):
 if attempts<self.retryAttempts:
 #put connecting code here
 if connectionFailed:
 self.connect(attempt+1)
 def diconnectSocket(self):
 #perform all breakdown operations
 ...
 self.socket = None
 def sendDataToDB(self, data):
 #send data to db
 def readData(self):
 #read data here
 while True:
 if self.socket is None:
 self.connect()
 ...

Just make sure you properly disconnect the socket and set it to None.

answered Jul 31, 2013 at 16:30

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.