0

我正在尝试创建一个小程序,它将通过 TCP 记录从设备输出的信息

基本上,这只是将我想要捕获的数据流出来,然后转储到数据库中以供以后处理

但是设备会重新启动,因此我需要能够在套接字关闭时重新连接而不受任何人为干扰

所以这就是我到目前为止所拥有的

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()

如果尝试连接并且它不存在,这一切在启动时都可以正常工作,它将重试由 reconnectattemps 设置的次数

但他是我的问题

    while 1:
        s.recv(1034)

当这失败时我想尝试重新连接我当然可以输入或只是再次复制我的连接部分但我想要做的是调用一个函数来处理连接并重试并将连接对象交还给我

例如像这样

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()

我认为这是可能的,但我真的不明白类/方法系统在 python 中是如何工作的,所以我认为我在这里遗漏了一些东西

仅供参考,以防万一你没有注意到 iv 对 python 很陌生。也欢迎对我已有的任何其他评论:)

谢谢阿杰

4

2 回答 2

1

推荐

对于这个用例,我会推荐比套接字更高级别的东西。为什么?当您只想检索或发送数据并保持连接时,为自己控制所有这些异常和错误可能会很烦人。

当然,您可以使用简单的解决方案来实现您想要的,但是我认为您会更多地弄乱代码。无论如何,它看起来类似于amustafa编写的类,处理套接字错误以关闭/重新连接方法等。

例子

我为使用asyncore模块的更简单的解决方案做了一些示例:

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()方法在某种程度上是您案例的核心 - 当需要建立连接时调用它:当类初始化或连接中断时。 handle_read()操作任何收到的数据,在这里你记录它或其他东西。您甚至可以使用缓冲区(self.out_buffer += 'message')发送数据,重新连接后将保持不变,因此再次连接时类将恢复发送。设置self.endTrue将通知班级在可能的情况下退出。

asyncore在发生此类事件时处理异常和调用handle_close(),这是处理连接失败的便捷方式。

于 2013-08-06T23:05:14.093 回答
1

您应该查看 python 文档以了解类和方法的工作原理。python 方法和大多数其他语言中的方法最大的区别是添加了“self”标签。self 表示调用方法的实例,并由 python 系统自动输入。所以:

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()
            ...

只需确保正确断开套接字并将其设置为无。

于 2013-07-31T16:30:36.373 回答