Python中asyncore異步模塊的用法及實(shí)現(xiàn)httpclient的實(shí)例
基礎(chǔ)
這個(gè)模塊是socket的異步實(shí)現(xiàn),讓我們先來熟悉一下模塊中的一些類和方法:
1.asyncore.loop
輸入一個(gè)輪詢循環(huán)直到通過計(jì)數(shù)或打開的通道已關(guān)閉。
2.asyncore.dispatcher
dispatcher類是一個(gè)底層socket類的包裝對(duì)象。要使它更有用, 它有一部分事件處理方法被異步循環(huán)調(diào)用。否則它就是一個(gè)標(biāo)準(zhǔn)的非阻塞socket對(duì)象。
底層的事件在特定事件或特定的連接狀態(tài)告訴異步循環(huán),某些高級(jí)事件發(fā)生了。例如, 我們要求一個(gè)socket連接到另一個(gè)主機(jī)。
(1)handle_connect() 第一次讀或?qū)懯录?br />
(2)handle_close() 讀事件沒有數(shù)據(jù)可用。
(3)handle_accept 讀事件監(jiān)聽一個(gè)socket。
(4)handle_read
在異步循環(huán)察覺到通道呼叫read()時(shí)調(diào)用。
(5)handle_write
在異步循環(huán)檢測(cè)到一個(gè)可寫的socket可以寫的時(shí)候調(diào)用。這種方法經(jīng)常實(shí)現(xiàn)緩沖性能。比如
def handle_write(self): sent = self.send(self.buffer) self.buffer = self.buffer[sent:]
(6)handle_expt
當(dāng)有(OOB)數(shù)據(jù)套接字連接。這幾乎永遠(yuǎn)不會(huì)發(fā)生,因?yàn)镺OB精細(xì)地支持和很少使用。
(7)handle_connect
當(dāng)socket創(chuàng)建一個(gè)連接時(shí)調(diào)用。
(8)handle_close
當(dāng)socket連接關(guān)閉時(shí)調(diào)用。
(9)handle_error
當(dāng)引發(fā)一個(gè)異常并沒有其他處理時(shí)調(diào)用。
(10)handle_accept
當(dāng)本地監(jiān)聽通道與遠(yuǎn)程端建立連接(被動(dòng)連接)時(shí)調(diào)用。
(11)readable
每次在異步循環(huán)確定是否添加一個(gè)通道socket到讀事件列表時(shí)調(diào)用,默認(rèn)都為True。
(12)writable
每次在異步循環(huán)確定是否添加一個(gè)通道socket到寫事件列表時(shí)調(diào)用, 默認(rèn)為True。
(13)create_socket
與創(chuàng)建標(biāo)準(zhǔn)socket的時(shí)候相同。
(14)connect
與標(biāo)準(zhǔn)socket的端口設(shè)置是相同, 接受一個(gè)元組第一個(gè)參數(shù)為主機(jī)地址,第二個(gè)參數(shù)是端口號(hào)。
(15)send
向遠(yuǎn)程端socket發(fā)送數(shù)據(jù)。
(16)recv
從遠(yuǎn)程端socket讀取最多buffer_size的數(shù)據(jù)。一個(gè)空的字符串意味著從另一端通道已關(guān)閉。
(17)listen
監(jiān)聽socket連接。
(18)bind
將socket綁定到地址。
(19)accept
接受一個(gè)連接, 必須綁定到一個(gè)socket和監(jiān)聽地址。
(20)close
關(guān)閉socket。
3.asyncore.dispatcher_with_send
dispatcher子類添加了簡(jiǎn)單的緩沖輸出功能用于簡(jiǎn)單的客戶,更復(fù)雜的使用asynchat.async_chat。
4.asyncore.file_dispatcher
file_dispatcher需要一個(gè)文件描述符或文件對(duì)象地圖以及一個(gè)可選的參數(shù),包裝,使用調(diào)查()或循環(huán)()函數(shù)。如果提供一個(gè)文件對(duì)象或任何fileno()方法,該方法將調(diào)用和傳遞到file_wrapper構(gòu)造函數(shù)??捎眯?UNIX。
5.asyncore.file_wrapper
file_wrapper需要一個(gè)整數(shù)文件描述符并調(diào)用os.dup()復(fù)制處理,這樣原來的處理可能是獨(dú)立于file_wrapper關(guān)閉。這個(gè)類實(shí)現(xiàn)足夠的方法來模擬一個(gè)套接字使用file_dispatcher類??捎眯?UNIX。
asyncore 實(shí)例
1.一個(gè)http client的實(shí)現(xiàn)。
import socket
import asyncore
class Client(asyncore.dispatcher):
def __init__(self, host, path):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, 80))
self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path
def handle_connect(self):
pass
def handle_close(self):
self.close()
def handle_read(self):
print self.recv(8192)
def writable(self):
return (len(self.buffer) > 0)
def handle_write(self):
sent = self.send(self.buffer)
self.buffer = self.buffer[sent:]
client = Client('www.python.org', '/')
asyncore.loop()
服務(wù)器接受連接和分配任務(wù)
import socket
import asyncore
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
data = self.recv(8192)
if data:
self.send(data)
class EchoServer(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_add()
self.bind((host, port))
self.listen(5)
def handle_accept(self):
pair = self.accept()
if pair is not None:
sock, addr = pair
print 'Incoming connection from %s' % repr(addr)
handler = EchoHandler(sock)
server = EchoServer('localhost', 8080)
asyncore.loop()
2.利用asyncore的端口映射(端口轉(zhuǎn)發(fā))
import socket,asyncore
class forwarder(asyncore.dispatcher):
def __init__(self, ip, port, remoteip,remoteport,backlog=5):
asyncore.dispatcher.__init__(self)
self.remoteip=remoteip
self.remoteport=remoteport
self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((ip,port))
self.listen(backlog)
def handle_accept(self):
conn, addr = self.accept()
# print '--- Connect --- '
sender(receiver(conn),self.remoteip,self.remoteport)
class receiver(asyncore.dispatcher):
def __init__(self,conn):
asyncore.dispatcher.__init__(self,conn)
self.from_remote_buffer=''
self.to_remote_buffer=''
self.sender=None
def handle_connect(self):
pass
def handle_read(self):
read = self.recv(4096)
# print '%04i -->'%len(read)
self.from_remote_buffer += read
def writable(self):
return (len(self.to_remote_buffer) > 0)
def handle_write(self):
sent = self.send(self.to_remote_buffer)
# print '%04i <--'%sent
self.to_remote_buffer = self.to_remote_buffer[sent:]
def handle_close(self):
self.close()
if self.sender:
self.sender.close()
class sender(asyncore.dispatcher):
def __init__(self, receiver, remoteaddr,remoteport):
asyncore.dispatcher.__init__(self)
self.receiver=receiver
receiver.sender=self
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((remoteaddr, remoteport))
def handle_connect(self):
pass
def handle_read(self):
read = self.recv(4096)
# print '<-- %04i'%len(read)
self.receiver.to_remote_buffer += read
def writable(self):
return (len(self.receiver.from_remote_buffer) > 0)
def handle_write(self):
sent = self.send(self.receiver.from_remote_buffer)
# print '--> %04i'%sent
self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:]
def handle_close(self):
self.close()
self.receiver.close()
if __name__=='__main__':
import optparse
parser = optparse.OptionParser()
parser.add_option(
'-l','--local-ip',
dest='local_ip',default='127.0.0.1',
help='Local IP address to bind to')
parser.add_option(
'-p','--local-port',
type='int',dest='local_port',default=80,
help='Local port to bind to')
parser.add_option(
'-r','--remote-ip',dest='remote_ip',
help='Local IP address to bind to')
parser.add_option(
'-P','--remote-port',
type='int',dest='remote_port',default=80,
help='Remote port to bind to')
options, args = parser.parse_args()
forwarder(options.local_ip,options.local_port,options.remote_ip,options.remote_port)
asyncore.loop()
相關(guān)文章
利用Django框架中select_related和prefetch_related函數(shù)對(duì)數(shù)據(jù)庫查詢優(yōu)化
這篇文章主要介紹了利用Python的Django框架中select_related和prefetch_related函數(shù)對(duì)數(shù)據(jù)庫查詢的優(yōu)化的一個(gè)實(shí)踐例子,展示如何在實(shí)際中利用這兩個(gè)函數(shù)減少對(duì)數(shù)據(jù)庫的查詢次數(shù),需要的朋友可以參考下2015-04-04
win10安裝tesserocr配置 Python使用tesserocr識(shí)別字母數(shù)字驗(yàn)證碼
這篇文章主要介紹了win10安裝tesserocr配置 Python使用tesserocr識(shí)別字母數(shù)字驗(yàn)證碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
python標(biāo)識(shí)符的用法及注意事項(xiàng)
在本篇文章里小編給大家整理了一篇關(guān)于python標(biāo)識(shí)符的用法及注意事項(xiàng)相關(guān)內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。2021-09-09
python代碼實(shí)現(xiàn)煙花實(shí)例
這篇文章主要給大家分享了python煙花詳細(xì)的代碼,文章主要以python煙花的代碼展開全文,所以解說會(huì)比較少,代碼較多。喜歡的小伙伴可以參考一下,希望對(duì)你有所幫助2021-12-12
Python3.5 win10環(huán)境下導(dǎo)入kera/tensorflow報(bào)錯(cuò)的解決方法
這篇文章主要介紹了Python3.5 win10環(huán)境下導(dǎo)入keras/tensorflow報(bào)錯(cuò)的解決方法,較為詳細(xì)的分析了Python3.5在win10環(huán)境下導(dǎo)入keras/tensorflow提示錯(cuò)誤的原因與相關(guān)解決方法,需要的朋友可以參考下2019-12-12
Python+OpenCV實(shí)現(xiàn)圖像的全景拼接
這篇文章主要為大家詳細(xì)介紹了Python+OpenCV實(shí)現(xiàn)圖像的全景拼接,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03

