【问题标题】:Python Socket connection classPython Socket 连接类
【发布时间】:2013-07-31 06:49:34
【问题描述】:

我正在尝试创建一个小程序,该程序将记录通过 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 很陌生。也欢迎我已经拥有的任何其他 cmets :)

谢谢 阿杰

【问题讨论】:

    标签: python class function sockets python-3.x


    【解决方案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()
                ...
    

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

    【讨论】:

      【解决方案2】:

      推荐

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

      当然,您可以使用简单的解决方案来实现您想要的,但我认为您会更多地弄乱代码。无论如何,它看起来类似于 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.end 设置为True 将通知班级在可能的情况下退出。

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

      【讨论】:

      • 上面sn-p中的self.connected是什么?
      • @TomaszPlonka 它是asyncore.dispatcher 类的属性,表示套接字是否连接到某个端点。当self.connect((self.host, self.port)) 执行完成时,此属性会更新 - 如果发生错误self.connected = False,否则True
      猜你喜欢
      • 2017-11-22
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-15
      • 2020-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多