学习了socket后决定尝试使用框架,目标锁定了Twisted。

什么是Twisted?

  twisted是一个用python语言写的事件驱动的网络框架,他支持很多种协议,包括UDP,TCP,TLS和其他应用层协议,比如HTTP,SMTP,NNTM,IRC,XMPP/Jabber。 非常好的一点是twisted实现和很多应用层的协议,开发人员可以直接只用这些协议的实现。其实要修改Twisted的SSH服务器端实现非常简单。很多时候,开发人员需要实现protocol类。

  一个Twisted程序由reactor发起的主循环和一些回调函数组成。当事件发生了,比如一个client连接到了server,这时候服务器端的事件会被触发执行。

基于事件:

  事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。另外两种常见的编程范式是(单线程)同步以及多线程编程。

  来比较和对比一下单线程、多线程以及事件驱动编程模型。图21.1展示了随着时间的推移,这三种模式下程序所做的工作。这个程序有3个任务需要完成,每个任务都在等待I/O操作时阻塞自身。阻塞在I/O操作上所花费的时间已经用灰色框标示出来了。

  

 

  在单线程同步模型中,任务按照顺序执行。如果某个任务因为I/O而阻塞,其他所有的任务都必须等待,直到它完成之后它们才能依次执行。这种明确的执行顺序和串行化处理的行为是很容易推断得出的。如果任务之间并没有互相依赖的关系,但仍然需要互相等待的话这就使得程序不必要的降低了运行速度。

  在多线程版本中,这3个任务分别在独立的线程中执行。这些线程由操作系统来管理,在多处理器系统上可以并行处理,或者在单处理器系统上交错执行。这使得当某个线程阻塞在某个资源的同时其他线程得以继续执行。与完成类似功能的同步程序相比,这种方式更有效率,但程序员必须写代码来保护共享资源,防止其被多个线程同时访问。多线程程序更加难以推断,因为这类程序不得不通过线程同步机制如锁、可重入函数、线程局部存储或者其他机制来处理线程安全问题,如果实现不当就会导致出现微妙且令人痛不欲生的bug。

  在事件驱动版本的程序中,3个任务交错执行,但仍然在一个单独的线程控制中。当处理I/O或者其他昂贵的操作时,注册一个回调到事件循环中,然后当I/O操作完成时继续执行。回调描述了该如何处理某个事件。事件循环轮询所有的事件,当事件到来时将它们分配给等待处理事件的回调函数。这种方式让程序尽可能的得以执行而不需要用到额外的线程。事件驱动型程序比多线程程序更容易推断出行为,因为程序员不需要关心线程安全问题

  

  体现在代码中,在定义协议时,事件方法会在相应事件发生时被调用,比如在接收新的连接或丢失连接时:

def connectionMade(self):                       #在得到连接时触发
self.transport.write('ftp-server: welcome to ftp!') #输出信息到客户端
print 'Got connection from ',self.transport.client def connectionLost(self, reason): #在失去连接时触发
print self.transport.client,'disconnect'

  当有数据需要被接收时,dataReceived方法被调用:

def dataReceived(self,data)
   print data

  如果想实现只接收了一整行就调用事件处理方法可以使用lineReceived方法。注意,之后每接收一行都会调用一次事件方法...

def lineReceived(self, line):
print line

异步:

  Twisted 官方称,“Twisted is event-based, asynchronous framework ”。这个“异步”功能的代表就是 deferred  

deferred 的作用类似于“多线程”,负责保障多头连接、多项任务的异步执行。
但deferred “异步”功能的实现,与多线程完全不同,具有以下特点:

1. deferred 产生的 event,是函数调用返回的对象;

2. deferred 代表一个连接任务,负责报告任务执行的延迟情况和最终结果;

3. 对deferred 的操作,通过预定的“事件响应器”(event handler)进行。

有了deferred,即可对任务的执行进行管理控制。防止程序的运行,由于等待某项任务的完成而陷入阻塞停滞,提高整体运行的效率。

defered貌似有很多实现方式,我只学会了下面这种

def upload(self,path,content):                  #定义一个根据客户端请求写文件的方法,写完后生成一个hash码用于验证
with open(path,'wb') as f:
f.write(content)
with open(path,'rb') as f: #hmac验证
h = hmac.new('liqixuan')
h.update(f.read())
file_hash = h.hexdigest()
print(file_hash)
self.sendLine(file_hash) d = threads.deferToThread(self.upload,'D:/client_new.py',s) #生成defered对象,异步调用写文件方法
d.addCallbacks(self.finash,self.failed)

刚接触框架,还一头雾水,继续学习中,贴上一个练手代码:

功能:异地上传文件,文件异步传输,通过hash码验证文件的完整性

server:

#!/usr/bin/env python
#-*- coding:utf-8 -
from twisted.internet import reactor
from twisted.internet.protocol import Protocol,Factory
from twisted.protocols.basic import LineOnlyReceiver
import os,hmac
from twisted.internet import defer,threads '''
定义一个协议类,在一个新的连接到达时,创建这个协议对象的factory。
此协议类继承LineOnlyReceiver,在得到连接时触发connectionMade方法,
失去连接时触发connectionLost方法,接收数据时会每接收一行就触发一次lineReceived方法。
使用defered异步处理文件I/O
'''
class MyTwisted(Protocol): d def connectionMade(self): #在得到连接时触发
self.transport.write('ftp-server: welcome to ftp!') #输出信息到客户端
self.path = '' #初始化一些字段
self.li = []
self.begin = False
self.end = False
print 'Got connection from ',self.transport.client def connectionLost(self, reason): #在失去连接时触发
print self.transport.client,'disconnect' def finash(self,arg): #定义两个回调方法,对应执行成功和失败
print 'Finashed!' def failed(self,arg):
print 'Failed' def upload(self,path,content): #定义一个根据客户端请求写文件的方法,写完后生成一个hash码用于验证
with open(path,'wb') as f:
f.write(content)
with open(path,'rb') as f: #hmac验证
h = hmac.new('liqixuan')
h.update(f.read())
file_hash = h.hexdigest()
print(file_hash)
self.sendLine(file_hash) def lineReceived(self, line):
'''
由于每接收一行就会调用该方法,故每次需要对传输内容进行判断
''' #接收客户端发送的上传文件路径
if line.startswith('path_filename'):
self.path = line.replace('path_filename','')
if os.path.isdir(line):
self.sendLine('True') #反馈客户端
else:
self.sendLine('False') #反馈客户端 '''
开始接收文件内容时触发的事件
'''
if line.startswith('*begin*'): #设置一个文件开始位,标志开始传输文件内容
self.begin = True
line = line.replace('*begin*','') if '*end*' in line and '*begin*' not in line: #结束位
self.end = True
line = line.replace('*end*','') if self.begin: #为结束前将文件内容写进某个字段
self.li.append('%s\r\n' % line) if self.end: #收到结束标志后开始准备传输文件
self.begin = False #重置标志位
self.end = False
s = ''.join(self.li[:-1]) #去掉最后换行符 d = threads.deferToThread(self.upload,'D:/client_new.py',s) #生成defered对象,异步调用写文件方法
d.addCallbacks(self.finash,self.failed) #执行完毕后回调相应方法 factory = Factory()
factory.protocol = MyTwisted reactor.listenTCP(8000,factory)
reactor.run()

client:

#-*- coding:utf-8 -*-
import socket,os,hmac def upload():
local_path = raw_input('本地文件: ').strip()
if os.path.isfile(local_path):
upload_path = raw_input('文件上传路径: ').strip()
file_name = os.path.basename(local_path) sk.send('path_filename%s%s\r\n' % (upload_path,file_name)) #发送目标路径及文件名 answer = sk.recv(1024) #接收反馈,若路径不存在退出
if answer == 'False':
print('No such file or directory')
return
else:
print('ready to upload...') with open(local_path,'rb')as f: #若存在读文件
s = f.read()
s = '*begin*%s*end*\r\n' % s #添加首尾标志位并发送服务器
sk.send(s)
file_hash = sk.recv(1024) #接收反馈的hash码
file_hash = file_hash.replace('\r\n','')
print("target file's HASH is ",file_hash)
with open(local_path,'rb') as f: #得到原文件hash码
h = hmac.new('liqixuan')
h.update(f.read())
hash1 = h.hexdigest()
print("local file's HASH is",hash1)
if hash1 == file_hash: #若一致则上传成功
print 'file upload successful!'
else:
print 'file upload failed!' ip_port = ('127.0.0.1',8000)
sk = socket.socket()
sk.connect(ip_port)
server_data = sk.recv(1024)
print(server_data)
upload()

  

Twisted随笔的更多相关文章

  1. AI人工智能系列随笔

    初探 AI人工智能系列随笔:syntaxnet 初探(1)

  2. 【置顶】CoreCLR系列随笔

    CoreCLR配置系列 在Windows上编译和调试CoreCLR GC探索系列 C++随笔:.NET CoreCLR之GC探索(1) C++随笔:.NET CoreCLR之GC探索(2) C++随笔 ...

  3. C++随笔:.NET CoreCLR之GC探索(4)

    今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...

  4. C++随笔:从Hello World 探秘CoreCLR的内部(1)

    紧接着上次的问题,上次的问题其实很简单,就是HelloWorld.exe运行失败,而本文的目的,就是成功调试HelloWorld这个控制台应用程序. 通过我的寻找,其实是一个名为TryRun的文件出了 ...

  5. ASP.NET MVC 系列随笔汇总[未完待续……]

    ASP.NET MVC 系列随笔汇总[未完待续……] 为了方便大家浏览所以整理一下,有的系列篇幅中不是很全面以后会慢慢的补全的. 学前篇之: ASP.NET MVC学前篇之扩展方法.链式编程 ASP. ...

  6. Mina、Netty、Twisted一起学(八):HTTP服务器

    HTTP协议应该是目前使用最多的应用层协议了,用浏览器打开一个网站就是使用HTTP协议进行数据传输. HTTP协议也是基于TCP协议,所以也有服务器和客户端.HTTP客户端一般是浏览器,当然还有可能是 ...

  7. 使用Beautiful Soup编写一个爬虫 系列随笔汇总

    这几篇博文只是为了记录学习Beautiful Soup的过程,不仅方便自己以后查看,也许能帮到同样在学习这个技术的朋友.通过学习Beautiful Soup基础知识 完成了一个简单的爬虫服务:从all ...

  8. 利用Python进行数据分析 基础系列随笔汇总

    一共 15 篇随笔,主要是为了记录数据分析过程中的一些小 demo,分享给其他需要的网友,更为了方便以后自己查看,15 篇随笔,每篇内容基本都是以一句说明加一段代码的方式, 保持简单小巧,看起来也清晰 ...

  9. 《高性能javascript》 领悟随笔之-------DOM编程篇(二)

    <高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...

随机推荐

  1. dagger2记录篇

    作为一个码农,什么都不用多讲,贴代码 build project build module Application public class App extends Application { pri ...

  2. 最新GHOST XP系统下载旗舰增强版 V2016年

    系统来自:系统妈:http://www.xitongma.com 深度技术GHOST xp系统旗舰增强版 V2016年3月 系统概述 深度技术ghost xp系统旗舰增强版集合微软JAVA虚拟机IE插 ...

  3. 在Java中使用xpath对xml解析

    xpath是一门在xml文档中查找信息的语言.xpath用于在XML文档中通过元素和属性进行导航.它的返回值可能是节点,节点集合,文本,以及节点和文本的混合等.在学习本文档之前应该对XML的节点,元素 ...

  4. 使用Hudson进行持续集成

    小Alan最近接了一个任务,就是使用Hudson进行持续集成,持续集成是怎么个概念,3言2语也说不清,有兴趣的童鞋去找我二奶度娘问问就知道了,说到Hudson就不得不提一下jenkins,目前来说用j ...

  5. 高级数据过滤(like)

    单字符过滤 '_' select * from T_Employee where FName like  '_erry' 多字符过滤 '%' select * from T_Employee wher ...

  6. PHP相关笔记

    扩展包(相关链接):https://packagist.org/: 插件postman主要应用于web开发时get.post请求时查看其响应:

  7. PHP核心技术与最佳实践——全局浏览

    难得买到并喜欢一本好书,‘PHP核心技术与最佳实践’. 几天时间,先看了个大概,总结一下整体是什么样子的,怎么看怎么学. 1.总共14章: 2.第1.2章讲PHP的OOP: 其中第一章侧重于PHP的O ...

  8. 项目游戏开发日记 No.0x000003

    14软二杨近星(2014551622) 刚刚过去清明节, 意味着离交项目的时间, 还有三个星期, 有点着急了, 可是, 还是觉得无所适从... 项目进展: 刚刚过去的一周, 事非常多, 以至于, 进展 ...

  9. 个人CTF资源聚合

    i春秋 幻泉 CTF入门课程笔记 视频地址 能力 思维能力 快速学习能力 技术能力 基础 编程基础 (c语言 汇编语言 脚本语言) 数学基础 (算法 密码学) 脑洞 (天马行空的想象推理) 体力耐力( ...

  10. Hash 函数及其重要性

    不时会爆出网站的服务器和数据库被盗取,考虑到这点,就要确保用户一些敏感数据(例如密码)的安全性.今天,我们要学的是 hash 背后的基础知识,以及如何用它来保护你的 web 应用的密码. 申明 密码学 ...