Twisted是历史悠久的开发框架,reactor的事件驱动是它的优点。
网上查阅中,很多都是直接进行调用,继承然后重写方法。但是在实际工程中,很少会通过继承的方式去继承使用一个框架。同样也不可以通过构造函数额方式传进去。假设我们要使用的框架是class B,我们要新建一个class A,当然这个类中不传入任何参数,直接在里面进行对B的调用。在A中封装好我们要实现的功能函数,然后在主函数中,首先实例化一个A,然后再调用A即可。以下是Python中Twisted的代码。
#coding:UTF-8
import os
import twisted
import twisted.internet.protocol
import twisted.internet.reactor #触发器
import twisted.internet.task
from utils1.Logger import Log
# from CatchPicture import CsiCatchPicture
from utils1.ReadConfig import Con
from CatchPicture import DelPicture
from time import sleep
from utils1 import date
logger = Log('Client_twisted').getlog()
SERVER_HOST = "192.168.155.1" #服务主机
SERVER_PORT = int(23456) #连接端口号
import twisted.internet.protocol
'''
A 自己的 功能与客户端连接
用Protocol实例化对象 声明 变量,
三各类,A,B,C(主函数) 主函数要调用b(相当于框架),a(自己定义的),在a里面声明b的变量,在b里面有方法,C里面实例化a,a去调B。
类和类之间,一般不是构造函数的调用的,不在构造类的时候传类的实例,一般都用组合。不能用继承
两个类之间互相调用,不要通过传参,在一个类
搜索:python之间类和类的组合调用
'''
class A(): # =mytwisted
def __init__(self):
self.home=B('skt').p()+'s'
def pr(self):
print(self.home)
class B(object):#twisted
def __init__(self,name):
self.name = name
def p(self):
return str(self.name)
SERVER_HOST = "192.168.191.1" # 服务主机
SERVER_PORT = int(23456) # 连接端口号
class MyTwisted():
def __init__(self):
pass
# self.myprotocol= twisted.internet.protocol.Protocol()
# self.myfactory=twisted.internet.protocol.ClientFactory()
#设置twisted相关数据
def SettingTwisted(self):#设置twisted相关
self.myprotocol= twisted.internet.protocol.Protocol
self.myprotocol.transport = twisted.internet.protocol.ProtocolToConsumerAdapter # 调用,使transport可以有write方法进行数据传输
self.myfactory=twisted.internet.protocol.ClientFactory
self.myfactory.protocol = self.myprotocol
'''---------------设置函数-------------------------------'''
self.myfactory.clientConnectionLost = self.clientConnectionLost
self.myfactory.clientConnectionFailed = self.clientConnectionFailed
# 下行:自己写类,进行覆盖。设置transport属性,并调用connectionMade()回调。
self.myprotocol.makeConnection = self.makeConnection
self.myprotocol.connectionMade=self.connectionMade #自己写类,进行覆盖 ,此函数在连接时运行
self.myprotocol.dataReceived = self.dataReceived
retries = 0
_callID = None
connector = None
clock = None
delay = 5 #设定尝试重新连接的秒数
'''----------------连接失败时执行的函数---------------------------'''
def clientConnectionFailed(self, connector, reason):
self.connector = connector
print("连接失败,尝试重新连接")
self.retry()
'''----------------连接失去时执行的函数---------------------------'''
def clientConnectionLost(self, connector, unused_reason):
while connector :
self.connector = connector
print("失去连接,尝试重新连接")
self.retry()
if connector is not None:
break
'''----------------重试连接---------------------------'''
def retry(self, connector=None):
if connector is None:
if self.connector is None:
raise ValueError("no connector to retry")
else:
connector = self.connector
self.retries += 1
print("第"+str(self.retries)+"次尝试重新连接...")
def reconnector():
self._callID = None
connector.connect()
if self.clock is None:
from twisted.internet import reactor
self.clock = reactor
self._callID = self.clock.callLater(self.delay, reconnector)
'''-------连接服务器,调用reactor----'''
def connect(self):
self.SettingTwisted()
import twisted.internet.reactor # 触发器
twisted.internet.reactor.connectTCP(SERVER_HOST, SERVER_PORT, self.myfactory()) # 连接服务器
twisted.internet.reactor.run() # 程序运行
'''-----------------------此函数用来设置transport属性,回调connectionMade()-------------'''
connected = 0
transport = None
def makeConnection(self,transport):
"""
Make a connection to a transport and a server.
This sets the 'transport' attribute of this Protocol, and calls the
connectionMade() callback.
"""
self.myprotocol.connected = 1
self.myprotocol.transport = transport
self.myprotocol.connectionMade()
'''----------连接上函数时执行-----------------------'''
def connectionMade(self):
print("连接数据库成功...")
logger.info("Connetcion is successful...")
print("服务器连接成功,可以进行数据交互...")
# logger.info("本机:和主机:连接成功")
# self.send() # 建立简介后就进行数据的发送
# print("服务器IP:"+str(self.transport.getHost()))
# print("客户端IP:"+str(self.transport.getPeer()))
# self.printhe()
# self.send_databag()
# self.send_picture()
# 创建定时任务,定时循环调用
# # sleep(2)
# task2 = twisted.internet.task.LoopingCall(self.TakeAndSendPicture) #定时拍照,并上传,此处应有一个图像识别
# task2.start(80) #yi个小时
sleep(1.5)
task1 = twisted.internet.task.LoopingCall(self.send_databag) # 定时发送数据包
##开启定时任务,并指定定时任务的时间间隔
task1.start(2) # 0.5个小时
# sleep(1.5)
# task3 = twisted.internet.task.LoopingCall(self.DelPicture) # 定时拍照,并上传,此处应有一个图像识别
# task3.start(3600)#24个小时
# task3 = twisted.internet.task.LoopingCall(DelPicture.delpicture)#定时删除
# task3.start(72000)
def dataReceived(self, data): # 接收服务端数据
print(data.decode("UTF-8")) # 输出接收到的数据
# self.send_databag() #继续发送数据
# def send_picture(self, date): # 发送图片,按照固定的检索目录
# picture_path = CsiCatchPicture.GetPicturePath() + str(date) + '.jpg'
# while 1:
# filepath = picture_path
# if os.path.isfile(filepath):
# fp = open(filepath, 'rb')
# while 1:
# data = fp.read(1024)
# if not data:
# logger.info(filepath + " is send over.")
# break
# self.transport.write(data)
# # self.transport.loseConnection() # 关闭连接
# sleep(2)
# else:
# logger.error("can not find the file...")
# break
def send(self): # 数据发送,自定义的方法
input_data = input("请输入要发送的数据:")
if input_data: # 有输入内容
self.transport.write(input_data.encode("UTF-8"))
else: # 没有有输入内容表示操作结束
self.transport.loseConnection() # 关闭连接
# def TakeAndSendPicture(self): # 封装的函数:先照相再发照片
#
# date1 = CsiCatchPicture.TakePhoto(date.GetDate()[0])
# sleep(5)
# self.send_picture(date1)
# def DelPicture(self): # 执行此函数,如果没有目录的话,os.remove失败,整个系统会直接弹出
# DelPicture.delpicture()
# logger.info("执行删除照片函数结束")
def send_databag(self): # 发送数据包
# self.connected
databag = ''
begin_flag = '<'
end_flag = '>'
brace1 = '{'
brace2 = '}'
machine_code = 'BM000001' # 机器编码 算上括号 10 byte
elect = 'DL12.5' # 电量 算上括号 8 byte
temper = 'WD+100.3' # 温度 算上括号 10 byte
humidity = 'SD100' # 湿度 算上括号 7 byte
SIMID = 'SMXXXXX' # SIM卡号 算上括号 24 byte
Motor_state = 'DJ00' # 电机状态 算上括号 6 byte
weight = 'ZL9999' # 重量 算上括号 8 byte
IP = 'IP' + self.myprotocol.transport.getHost().host # IP地址 不定长,getsockname()函数[1]是端口号
GPS = 'JW,V,,,,,,,,,,N*XX' # GPS地址 不定长
databag = databag + begin_flag + brace1 + machine_code + brace2 + brace1 + elect + brace2 + brace1 + temper + brace2 + brace1 + humidity + \
brace2 + brace1 + SIMID + brace2 + brace1 + Motor_state + brace2 + \
brace1 + weight + brace2 + brace1 + IP + brace2 + brace1 + GPS + brace2 + end_flag
'''-----------socket发送数据-------------'''
try:
# 有输入内容
self.myprotocol.transport.write(databag.encode("UTF-8"))
sleep(2)
# 没有有输入内容表示操作结束
# self.transport.loseConnection() # 关闭连接
except:
logger.error("The databag send to Client is fail")
else:
logger.info("The databag send to Client is success")
# print("databag send over...")
if __name__ == '__main__':
# a=A()
# a.pr()
b=MyTwisted()#实例化
b.connect()#调用函数
print("hello")
加粗样式
当然,twisted框架中很多事件函数,比如connectionMade,connectLost等,不用继承的话我们要在class A中写一个函数,然后用=替换即可。详情请见代码。如有错误,希望你能私信给我改正,谢谢。