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

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.

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.

Comments

Your Answer

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.