日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python 网络编程----非阻塞或异步编程

發布時間:2023/12/9 python 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python 网络编程----非阻塞或异步编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

From:?http://blog.chinaunix.net/uid-20730371-id-765038.html

非阻塞或異步編程
例如,對于一個聊天室來說,因為有多個連接需要同時被處理,所以很顯然,阻塞或同步的方法是不合適的,這就像買票只開了一個窗口,佷多人排隊等一樣。那么我們如何解決這個問題呢?主要有三種方法:forking、threading、異步I/O。

Forking和threading的方法非常簡單,通過使用SocketServer服務類的min-in類就可以實現。forking只適用于類Unix平臺;threading需要注意內存共享的問題。
異步I/O如果底層的方法來實現是有點困難的。要簡單點,我們可以考慮使用標準庫中的框架或Twisted(Twisted是一個非常強大的異步網絡編程的框架)。

一、用ScoketServer實現Forking和threading

下面我們使用兩個例子來分別創建forking服務器和threading服務器。

Forking?服務器

from?SocketServer?import?TCPServer,?ForkingMixIn,?StreamRequestHandler

class?Server(ForkingMixIn,?TCPServer):?pass

class?Handler(StreamRequestHandler):
????def?handle(self):
????????addr?=?self.request.getpeername()
????????print?'Got?connection?from',?addr
????????self.wfile.write('Thank?you?for?connecting')

server?=?Server(('',?1234),?Handler)
server.serve_forever()


threading服務器

from?SocketServer?import?TCPServer,?ThreadingMixIn,?StreamRequestHandler

class?Server(ThreadingMixIn,?TCPServer):?pass

class?Handler(StreamRequestHandler):
????def?handle(self):
????????addr?=?self.request.getpeername()
????????print?'Got?connection?from',?addr
????????self.wfile.write('Thank?you?for?connecting')

server?=?Server(('',?1234),?Handler)
server.serve_forever()


二、使用select實現異步I/O

所謂異步I/O,打個比方,就是如果一大群人都想你聽他說話,那么你就給他們每人一分鐘的時間說,大家輪流說,沒說完的待會兒輪到時再繼續說。也就是一個時間片的方法。

要實現異步I/O,我們可以通過使用框架asyncore/asynchat或Twisted,它們都是基于select函數或poll函數(poll只適于類Unix系統)的。select和poll函數都來自select模塊。

select 函數要求三個必須序列作為參數和一個可選的以秒為單位的超時值。序列中是表示文件描述符的整數值,它們是我們要等待的連接。這三個序列是關于輸入、輸出和 異常條件的。如果超時值沒有給出的話,select將處于阻塞狀態(也就是等待)直到有文件描述符準備動作。如果超時值給出了,那么select只阻塞給 定的時間。如果超時值是0的話,那么將不阻塞。select返回的值是一個由三個序列組成的元組,它們分別代表相應參數的活動的子集。例如,第一個序列返 回的是用于讀的輸入文件描述符構成的序列。

序列可以包含文件對象(不適于Windows)或socket。下面這個例子創建一個使用 select去服務幾個連接的服務器(注意:服務端的socket自身也提供給了select,以便于它能夠在有新的連接準備接受時發出信號通知)。這個 服務器只是簡單地打印接受自客戶端的數據。你可以使用telnet(或寫一個基于socket的簡單的客戶端)來連接測試它。

select?server

import?socket,?select

s?=?socket.socket()
host?=?socket.gethostname()
port?=?1234
s.bind((host,?port))

s.listen(5)
inputs?=?[s]
while?True:
????rs,?ws,?es?=?select.select(inputs,?[],?[])
????for?r?in?rs:
????????if?r?is?s:
????????????c,?addr?=?s.accept()
????????????print?'Got?connection?from',?addr
????????????inputs.append(c)
????????else:
????????????try:
????????????????data?=?r.recv(1024)
????????????????disconnected?=?not?data
????????????except?socket.error:
????????????????disconnected?=?True

????????????if?disconnected:
????????????????print?r.getpeername(),?'disconnected'
????????????????inputs.remove(r)
????????????else:
????????????????print?data





三、Twisted

Twisted 是針對Python的一個事件驅動的網絡框架,最初是為了網絡游戲而開發的,但是現在被應用于各類網絡軟件。用Twisted,你可以實現事件處理器,非 常類似用GUI工具包(Tk,?GTK,?Qt,?wxWidgets)。這部分我將介紹一些基本的概念和演示如何使用Twisted來做一些相對簡單的 網絡編程。Twisted是非常強大的框架并提供了大量的支持,如:Web服務器和客戶端、 SSH2,?SMTP,?POP3,?IMAP4,?AIM,?ICQ,?IRC,?MSN,Jabber,?NNTP,?DNS等等。

早先我們所寫的基于socket的服務器,它們都有一個顯示的事件循環:尋找新的連接和新的數據;基于SocketServer的服務器有一個隱含的循環:尋找連接和為連接創建處理器。但時處理器仍然時顯示的讀數據。

而 Twisted使用了更多的基于事件的方式。要寫一個基本的服務器,你要實現事件處理器,它處理諸如一個新的客戶端連接、新的數據到達和客戶端連接中斷等 情況。在Twisted中,你的事件處理器定義在一個protocol中;你也需要一個factory,當一個新的連接到達時它能夠構造這個 protocol對象,但是如果你僅僅想創建一個自定義的Protocol類的實例的話,你可以使用來自Twisted的factory,Factory 類在模塊twisted.internet.protocol中。當你寫你的protocol時,使用 twisted.internet.protocol模塊中的Protocol作為你的父類。當你得到一個連接時,事件處理器 connectionMade被調用;當你丟失了一個連接時,connectionLost被調用。從客戶端接受數據使用處理器 dataReceived。但是你不能使用事件處理策略向客戶端發送數據;要向客戶端發送數據,你可以使用self.transport,它有一個 write方法。它也有一個client屬性,其中包含了客戶端的地址(主機名和端口)。

下面這個例子是一個Twisted版的服務器。 其中實例化了Factory并設置了它的protocol屬性以便它知道使用哪個protocol與客戶端通信(這就是所謂的你的自定義 protocol)。然后你使用factory開始監聽指定的端口,factory通過實例化的protocol對象處理連接。監聽使用reactor模 塊中的listenTCP函數。最后,你通過調用reactor模塊中的run函數來開始服務器。

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

#?定義你Protocol類
class?SimpleLogger(Protocol):

????def?connectionMade(self):
????????print?'Got?connection?from',?self.transport.client
????def?connectionLost(self,?reason):
????????print?self.transport.client,?'disconnected'
????def?dataReceived(self,?data):
????????print?data


#?實例化Factory

factory?=?Factory()

#?設置factory的protocol屬性以便它知道使用哪個protocol與客戶端通信(這就是所謂的你的自定義
#?protocol)

factory.protocol?=?SimpleLogger

#?監聽指定的端口

reactor.listenTCP(1234,?factory)

#?開始運行主程序
reactor.run()


為 你的處理目的而寫一個自定義的protocol是很容易的。模塊twisted.protocols.basic中包含了幾個有用的已存在的 protocol,其中的LineReceiver執行dataReceived并在接受到了一個完整的行時調用事件處理器lineReceived。如 果當你在接受數據時除了使用lineReceived,還要做些別的,那么你可以使用LineReceiver定義的名為rawDataReceived 事件處理器。下面是一使用LineReceiver的服務器例子:

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

class?SimpleLogger(LineReceiver):

????def?connectionMade(self):
????????print?'Got?connection?from',?self.transport.client
????def?connectionLost(self,?reason):
????????print?self.transport.client,?'disconnected'
????def?lineReceived(self,?line):
????????print?line

factory?=?Factory()
factory.protocol?=?SimpleLogger
reactor.listenTCP(1234,?factory)
reactor.run()

總結

以上是生活随笔為你收集整理的python 网络编程----非阻塞或异步编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。