http://50vip.com/316.html
http://my.oschina.net/u/1433482/blog/190696
在這里我先介紹一下與python中集成類庫asyncore相關的內容。
首先,可以看看python官網對於asyncore的解釋(asyncore)。
This module provides the basic infrastructure for writing asynchronous socket service clients and servers.(這個模塊為異步socket的服務器客戶端通信提供簡單的接口)。這個里面有一個重要的類asyncore.dispatcher,利用asynscore進行異步socket讀寫的時候,一般是采用繼承asyncore.dispatcher,然后覆寫該類的基本方法即可。
該模塊提供了異步socket服務客戶端和服務器的基礎架構。
只有兩種方法讓程序在單個處理器上的同時做超過一件的事情。 多線程編程是最簡單,最普遍的方式,但還有另一種非常不同的技術,可以讓你具有多線程幾乎所有的優點,實際上並沒有使用多線程。程序的瓶頸主要在於I/O時是比較可行的。如果你的程序的瓶頸在處理器,確實需要多線程,不過網絡服務器的瓶頸大多在I/O。
如果您的操作系統支持I/O庫的select()系統調用(一般都支持) ,那么你可以使用它同時處理多個通信信道,做其他的工作的同時讓I/O在后台執行,這比多線程更容易理解。
asyncore和asynchat的基本思路是創建一個或多個網絡通道,即asyncore.dispatcher和asynchat.async_chat的實例。然后添加到全局映射,如果你沒有創建自己的映射,可以直接使用loop()函數。loop()激活所有通道服務,執行直到最后一個通道關閉。
一、syncore.dispatcher中需要覆寫的方法
下面是官網列出asyncore.dispatcher中一般需要覆寫的方法:
1.handle_read():Called when the asynchronous loop detects that a read() call on the channel’s socket will succeed.
當socket有可讀的數據的時候執行這個方法,可讀的數據的判定條件就是看方法readable()返回為True還是False。即readable()返回為True的時候執行該方法。
2.handle_write():Called when the asynchronous loop detects that a writable socket can be written.
當socket有可寫的數據的時候執行這個方法,可寫的數據的判定條件就是看方法writable()返回為True還是False。即writable()返回為True的時候執行該方法。
3.handle_expt():Called when there is out of band (OOB) data for a socket connection.
當socket通信過程中出現OOB異常的時候執行該方法。
4.handle_connect():Called when the active opener’s socket actually makes a connection.
當有客戶端連接的時候,執行該方法進行處理。
5.handle_close():Called when the socket is closed.
可連接關閉的時候執行該方法。
6.handle_error():Called when an exception is raised and not otherwise handled.
當通信過程中出現異常並且沒有在其他的地方進行處理的時候執行該方法。
7.handle_accept():Called on listening channels (passive openers) when a connection can be established with a new remote endpoint that has issued a connect() call for the local endpoint.
當作為server socket監聽的時候,有客戶端連接的時候,利用這個方法進行處理。
8.readable():Called each time around the asynchronous loop to determine whether a channel’s socket should be added to the list on which read events can occur.
緩沖區是否有可讀數據。
9.writable():Called each time around the asynchronous loop to determine whether a channel’s socket should be added to the list on which write events can occur.
緩沖區是否有可寫數據。
二、syncore.dispatcher可以使用的方法
1.create_socket(family, type):創建一個socket連接。
2.connect(address):連接一個socket server。
3.send(data):發送數據。
4.recv(buffer_size):收取數據到內存緩沖中。
5.listen(backlog):server socket開始監聽。
6.bind(address):server socket綁定某個地址和端口。
7.accept():當有客戶端連接的時候,執行該方法接受客戶端連接。
8.close():關閉socket。
通過上面兩點的數據,對於python asyncore的使用已經大致清楚了,相比python原生的socket api,asyncore具備有很大的優勢,asyncore對原生的socket進行封裝,提供非常簡潔優秀的接口,利用asyncore覆寫相關需要處理的接口方法,就可以完成一個socket的網絡編程,從而不需要處理復雜的socket網絡狀況以及多線程處理等等。
-
asyncore.loop([timeout[, use_poll[, map[, count]]]])
進入輪詢循環直到所有打開的通道已被關閉或計數通過。所有的參數都是可選的。 count參數默認為None,只有當所有通道都被關閉時循環才會終止。 timeout參數設置為select()或poll()調用設置超時,以秒為單位,默認為30秒。use_poll參數,如果為true ,則表示 poll()優先於select(),默認值為False。map是包含監控的channel的字典。channel關閉時會從map中刪除。不指定map時會使用全局map。Channel(asyncore.dispatcher , asynchat.async_chat和其子類的實例)可以自由地混合在map上)。
-
asyncore.dispatcher_with_send:dispatcher的子類,增加了簡單的緩沖輸出,對於簡單的客戶端有用。詳細資料參考:asynchat.async_chat。
-
class asyncore.file_dispatcher:封裝了文件描述符或文件對象及映射參數(可選)供poll()和loop()函數使用的文件分發器。它提供了文件對象或其他具備fileno()方法的對象,調用fileno()並傳遞到file_wrapper構造函數。可用於UNIX。
-
class asyncore.file_wrapper:接收整數文件描述符並調用os.dup()復制句柄,這樣原句柄可以關閉,而文件包裝器不受影響。該類封裝了大量方法以模擬socket給file_dispatcher類使用。可用於UNIX。
HTTP客戶端實例
import
asyncore, socketclass HTTPClient(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
=
HTTPClient(
'192.168.4.13'
,
'/env.htm'
)
asyncore.loop()
import
asyncore
import socket
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_addr()
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()