Python asyncore异步socket封装模块用法总结
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()