基礎
這個模塊是socket的異步實現,讓我們先來熟悉一下模塊中的一些類和方法:
1.asyncore.loop
輸入一個輪詢循環直到通過計數或打開的通道已關閉。
2.asyncore.dispatcher
dispatcher類是一個底層socket類的包裝對象。要使它更有用, 它有一部分事件處理方法被異步循環調用。否則它就是一個標準的非阻塞socket對象。
底層的事件在特定事件或特定的連接狀態告訴異步循環,某些高級事件發生了。例如, 我們要求一個socket連接到另一個主機。
(1)handle_connect() 第一次讀或寫事件。
(2)handle_close() 讀事件沒有數據可用。
(3)handle_accept 讀事件監聽一個socket。
(4)handle_read
在異步循環察覺到通道呼叫read()時調用。
(5)handle_write
在異步循環檢測到一個可寫的socket可以寫的時候調用。這種方法經常實現緩沖性能。比如
1
2
3
|
def handle_write( self ): sent = self .send( self . buffer ) self . buffer = self . buffer [sent:] |
(6)handle_expt
當有(OOB)數據套接字連接。這幾乎永遠不會發生,因為OOB精細地支持和很少使用。
(7)handle_connect
當socket創建一個連接時調用。
(8)handle_close
當socket連接關閉時調用。
(9)handle_error
當引發一個異常并沒有其他處理時調用。
(10)handle_accept
當本地監聽通道與遠程端建立連接(被動連接)時調用。
(11)readable
每次在異步循環確定是否添加一個通道socket到讀事件列表時調用,默認都為True。
(12)writable
每次在異步循環確定是否添加一個通道socket到寫事件列表時調用, 默認為True。
(13)create_socket
與創建標準socket的時候相同。
(14)connect
與標準socket的端口設置是相同, 接受一個元組第一個參數為主機地址,第二個參數是端口號。
(15)send
向遠程端socket發送數據。
(16)recv
從遠程端socket讀取最多buffer_size的數據。一個空的字符串意味著從另一端通道已關閉。
(17)listen
監聽socket連接。
(18)bind
將socket綁定到地址。
(19)accept
接受一個連接, 必須綁定到一個socket和監聽地址。
(20)close
關閉socket。
3.asyncore.dispatcher_with_send
dispatcher子類添加了簡單的緩沖輸出功能用于簡單的客戶,更復雜的使用asynchat.async_chat。
4.asyncore.file_dispatcher
file_dispatcher需要一個文件描述符或文件對象地圖以及一個可選的參數,包裝,使用調查()或循環()函數。如果提供一個文件對象或任何fileno()方法,該方法將調用和傳遞到file_wrapper構造函數??捎眯?UNIX。
5.asyncore.file_wrapper
file_wrapper需要一個整數文件描述符并調用os.dup()復制處理,這樣原來的處理可能是獨立于file_wrapper關閉。這個類實現足夠的方法來模擬一個套接字使用file_dispatcher類??捎眯?UNIX。
asyncore 實例
1.一個http client的實現。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
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() |
服務器接受連接和分配任務
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
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的端口映射(端口轉發)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
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() |