搜尋
首頁後端開發Python教學使用Python的Twisted框架实现一个简单的服务器

预览
  twisted是一个被设计的非常灵活框架以至于能够让你写出非常强大的服务器。这种灵活的代价是需要好通过好几个层次来实现你的服务器, 本文档描述的是Protocol层,你将在这个层次中执行协议的分析和处理,如果你正在执行一个应用程序,那么你应该在读过top level的为twisted写插件一节中的怎样开始写twisted应用程序之后阅读本章。这个文档只是和TCP,SSL和Unix套接字服务器有关,同时也将有另一份文档专门讲解UDP。
  你的协议处理类通常是twisted.internet.protocol.Protocol的子类。许多协议处理继承于该类或者比该类更加方便的该类的子类。一个protocol类的实例可能反复连接,也可能在连接关闭之后销毁。这就意味着这些持续不断的配置信息不是保存在Protocol中。
   这些持久性的配置被保存在工厂(Factory)类中,这些工厂类通常继承至twisted.internet.protocol.Factory,默认 的工厂类仅仅是实例化每个Protocol,然后设置他们的factory属性为这个默认的工厂实例本身。这就让每个Protocol都被存储,然后可能 修改,于是这样就形成了Protocol的持久性。
   通常为多个端口或网络地址提供相同的服务是非常有用的。这就是为什么Factory不监听连接,并且实际上它不知道关于网络的任何事情。看 twisted.internet.interfaces.IReactorTCP.listenTCP,另一个IReactor*.listen*获得 更多的信息。


   本文档将要讲解各个步骤。


Protocol
    如上所述,这里将通过更多代码的辅助类和函数来了解它。一个twisted protocl通过异步方式处理数据。这就意味着protocol从不等待任何事件。相反的是在事件通过网络到达的时候作出响应。

from twisted.internet.protocol import Protocol
class Echo(Protocol):
 def dataReceived(self,data):
  self.transport.writed(data)

这是个非常简单的协议处理,仅仅是在获得数据的事件中简单的将接收到的数据发送回去,并没有对所有的事件进行响应。这里有一个Protocol响应其他事件的例子如下:

from twisted.internet.protocol import Protocol
class QOTD(Protocol):
 def connectionMade(self):
  self.transport.write("An apple a day keeps the doctor away/r/n") 
  self.transport.loseConnection()

    本Protocl在一个已知的引用刚开始连接上来的时候作出响应,发送了一条消息,然后终止了连接connectionMade事件通常是在由于连接对象建立初始连接时触发,就像上面的QOTD类实际上是RFC865号文档的一个协议基类connectionLost事件将在断开连接的时候触发。实例:  
       

<span style="font-family: Monospaced; color: #0000a0;"><strong>PythonCode: </strong></span><table style="width: 100%; height: 20px;" align="center" bgcolor="#e3dfe3" border="1" bordercolor="#9da7ac" cellpadding="0" cellspacing="0"> 
  <tbody><tr><td> 
     <div class="textBackGround" style="font-family:Courier New;font-size:9pt;"><pre class="brush:php;toolbar:false"><span style="color: blue;">from</span> twisted.internet.protocol <span style="color: blue;">import</span> Protocol 
 <span style="color: blue;">class</span> Echo(Protocol): 
  <span style="color: blue;">def</span> connectionMade(self): 
   self.factory.numProtocols = self.factory.numProtocols+1 
   <span style="color: blue;">if</span> self.factory.numProtocols > 100: 
    self.transport.write(<span style="color: #ff44a2;">"Too many connections, <span style="color: blue;">try</span> later"</span>) 
    self.transport.loseConnection() 
  <span style="color: blue;">def</span> connectionLost(self, reason): 
   self.factory.numProtocols = self.factory.numProtocols-1 
  <span style="color: blue;">def</span> dataReceived(self, data): 
   self.transport.write(data)

    本实例中,connectionMade和connectionLost相互协作工作以保持factory内部的活动连接数量最多为100。每当有用户协议连接近来的时候,就先检测factory内部的活动连接数,如果数量超过100,就发送连接数太多等下试的消息,然后断开连接而connectionLost则在断开一个协议的时候触发,减去factory内部的协议数量。

Using the Protocol

          在本节,我将要讲解怎样简单的去测试你的protocol。(想知道如何写出一个好的twisted的服务器,请看 Writing Plug-Ins
    for Twisted
),这里有一个代码将运行我们上面谈论的QOTD服务器:  
   

 <!-- 
 .textBackGround {background-color: #F0F5FD;} 
 --> 
  <span style="font-family: Monospaced; color: #0000a0;"><strong>PythonCode: </strong></span><table style="width: 100%; height: 20px;" align="center" bgcolor="#e3dfe3" border="1" bordercolor="#9da7ac" cellpadding="0" cellspacing="0"> 
  <tbody><tr><td> 
     <div class="textBackGround" style="font-family:Courier New;font-size:9pt;"><pre class="brush:php;toolbar:false"><span style="color: blue;">from</span> twisted.internet.protocol <span style="color: blue;">import</span> Protocol, Factory 
 <span style="color: blue;">from</span> twisted.internet <span style="color: blue;">import</span> reactor 
 <span style="color: blue;">class</span> QOTD(Protocol): 
  <span style="color: blue;">def</span> connectionMade(self): 
   self.transport.write(<span style="color: #ff44a2;">"An apple a day keeps the doctor away/r/n"</span>) 
   self.transport.loseConnection() 
  
 <span style="color: green;"># Next lines are magic:</span> 
 factory = Factory() 
 factory.protocol = QOTD 
  
 <span style="color: green;"># 8007 <span style="color: blue;">is</span> the port you want to run under. Choose something >1024</span> 
 reactor.listenTCP(8007, factory) 
 reactor.run()

    不必担心最后面的6条代码,稍后你将会在本文档中了解到他们。
 

Helper Protocols

     大部分protocols依赖于同类别的更低层次的超级类。最受欢迎的互联网协议是基于行,行通常是由CR_LF(回车换行组成)
然而,也有相当一部分协议是混合的,他们具有线性的基本节点,也有原始数据节点,比如HTTP/1.1。
     在这样的情况下,我们可以使用LineReceiver,本协议类有两个不同的事件处理方法,lineReceived和rawDataReceived
默认情况下,只有lineReceived会被调用,每次读取一行,然而如果setRawMode被调用,protocol将调用rawDataReceived
来处理直到setLineMode被调用。下面有一个简单的例子说明如何使用lineReceiver:

    PythonCode:             

from twisted.protocols.basic import LineReceiver
class Answer(LineReceiver):
 answers = {'How are you&#63;': 'Fine', None : "I don't know what you mean"}
 def lineReceived(self, line):
  if self.answers.has_key(line):
   self.sendLine(self.answers[line])
  else:
   self.sendLine(self.answers[None])

注意:界定符不是命令行的一部分
其他也有一些不流行的协议依然存在,比如netstring based 和 a prefixed-message-length

State Machines

     许多twisted protocol handlers需要编写一个状态机来记录他们当前的状态,这里有几点编写状态机的建议:
   1、不要编写大状态机,宁愿去实现一个抽象的状态机类
   2、使用python的动态性质去创建没有限制的状态机,比如SMTP客户端
   3、不要混合特定应用程序代码和协议处理代码,当协议处理器已经提出一个特别的具体要求,保持它作为一个方法调用。

Factories(工厂类)

     如前面所说,通常twisted.internet.protocol.Factory不必子类化就可以开始工作。然而有时候protocol需要具体的
特殊的工厂配置信息或其他需求,在这样的情况下,就需要进行子类化了。
    对于Factory来说,他只是简单的实例化特殊的 protocol协议类,实例化Factory,并且设置protocol属性:

    PythonCode:             

from twisted.internet.protocol import Factory
from twisted.protocols.wire import Echo

myFactory = Factory()
myFactory.protocol = Echo

如果需要简单的去构造一个有具体特殊信息的工厂类,那么一个factory函数是非常有用的:

PythonCode:

class QOTD(Protocol):
 def connectionMade(self):
  self.transport.write(self.factory.quote+'/r/n')
  self.transport.loseConnection()

def makeQOTDFactory(quote=None):
 factory = Factory()
 factory.protocol = QOTD
 factory.quote = quote or 'An apple a day keeps the doctor away'
 return factory


一个Factory有两个方法以执行特定于应用程序的建立和拆除(由于一个Factory通常存在,所以常规下一般不在__init__或者
__del__中给他们分配与回收,有可能太早或太晚)。
下面是一个Factory的例子,本例将允许Protocol写一个日志文件:   
PythonCode:

from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver

class LoggingProtocol(LineReceiver):

 def lineReceived(self, line):
  self.factory.fp.write(line+'/n')


class LogfileFactory(Factory):

 protocol = LoggingProtocol

 def __init__(self, fileName):
  self.file = fileName

 def startFactory(self):
  self.fp = open(self.file, 'a')

 def stopFactory(self):
  self.fp.close()

Putting it All Together(综合)

    现在你已经了解了Factory并且想要执行QOTD作为一个可配置的quote服务器是吗?没有问题这里就有一个代码:
    PythonCode:             

from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor

class QOTD(Protocol):

 def connectionMade(self):
  self.transport.write(self.factory.quote+'/r/n')
  self.transport.loseConnection()


class QOTDFactory(Factory):

 protocol = QOTD

 def __init__(self, quote=None):
  self.quote = quote or 'An apple a day keeps the doctor away'

reactor.listenTCP(8007, QOTDFactory("configurable quote"))
reactor.run()

就是最后两句代码,还需要去理解。
listenTCP是一个将Factory连接到网络的方法,他使用了reactor的接口,让许多不同的循环处理网络代码,而不需要修改的
最终用户代码,就像这样。如前面所说,如果你想要写一个好的twisted服务器,而不是仅仅的20行,那么你需要使用 the Application object.

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Numpy數組與使用數組模塊創建的數組有何不同?Numpy數組與使用數組模塊創建的數組有何不同?Apr 24, 2025 pm 03:53 PM

numpyArraysareAreBetterFornumericalialoperations andmulti-demensionaldata,而learthearrayModuleSutableforbasic,內存效率段

Numpy數組的使用與使用Python中的數組模塊陣列相比如何?Numpy數組的使用與使用Python中的數組模塊陣列相比如何?Apr 24, 2025 pm 03:49 PM

numpyArraySareAreBetterForHeAvyNumericalComputing,而lelethearRayModulesiutable-usemoblemory-connerage-inderabledsswithSimpleDatateTypes.1)NumpyArsofferVerverVerverVerverVersAtility andPerformanceForlargedForlargedAtatasetSetsAtsAndAtasEndCompleXoper.2)

CTYPES模塊與Python中的數組有何關係?CTYPES模塊與Python中的數組有何關係?Apr 24, 2025 pm 03:45 PM

ctypesallowscreatingingangandmanipulatingc-stylarraysinpython.1)usectypestoInterfacewithClibrariesForperfermance.2)createc-stylec-stylec-stylarraysfornumericalcomputations.3)passarraystocfunctions foreforfunctionsforeffortions.however.however,However,HoweverofiousofmemoryManageManiverage,Pressiveo,Pressivero

在Python的上下文中定義'數組”和'列表”。在Python的上下文中定義'數組”和'列表”。Apr 24, 2025 pm 03:41 PM

Inpython,一個“列表” isaversatile,mutableSequencethatCanholdMixedDatateTypes,而“陣列” isamorememory-sepersequeSequeSequeSequeSequeRingequiringElements.1)列表

Python列表是可變還是不變的?那Python陣列呢?Python列表是可變還是不變的?那Python陣列呢?Apr 24, 2025 pm 03:37 PM

pythonlistsandArraysareBothable.1)列表Sareflexibleandsupportereceneousdatabutarelessmory-Memory-Empefficity.2)ArraysareMoremoremoremoreMemoremorememorememorememoremorememogeneSdatabutlesserversEversementime,defteringcorcttypecrecttypececeDepeceDyusagetoagetoavoavoiDerrors。

Python vs. C:了解關鍵差異Python vs. C:了解關鍵差異Apr 21, 2025 am 12:18 AM

Python和C 各有優勢,選擇應基於項目需求。 1)Python適合快速開發和數據處理,因其簡潔語法和動態類型。 2)C 適用於高性能和系統編程,因其靜態類型和手動內存管理。

Python vs.C:您的項目選擇哪種語言?Python vs.C:您的項目選擇哪種語言?Apr 21, 2025 am 12:17 AM

選擇Python還是C 取決於項目需求:1)如果需要快速開發、數據處理和原型設計,選擇Python;2)如果需要高性能、低延遲和接近硬件的控制,選擇C 。

達到python目標:每天2小時的力量達到python目標:每天2小時的力量Apr 20, 2025 am 12:21 AM

通過每天投入2小時的Python學習,可以有效提升編程技能。 1.學習新知識:閱讀文檔或觀看教程。 2.實踐:編寫代碼和完成練習。 3.複習:鞏固所學內容。 4.項目實踐:應用所學於實際項目中。這樣的結構化學習計劃能幫助你係統掌握Python並實現職業目標。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)