我正在尝试创建一个小程序,它将通过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)
如果失败,我想尝试重新连接 我当然可以输出或只是再次复制我的连接部分,但我希望能够todo调用一个函数来处理连接并重试并将我交给连接对象
例如像这样
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中工作所以我想我在这里遗漏了什么
仅供参考,以防万一你没注意到我对python很新。对我已经拥有的任何其他评论也是受欢迎的:)
由于 AJ
答案 0 :(得分: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()
...
只需确保正确断开套接字并将其设置为无。
答案 1 :(得分: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.end
设置为True
会在可能的情况下通知班级退出。
asyncore
处理异常并在发生此类事件时调用handle_close()
,这是处理连接失败的便捷方法。