Python异步网络探

异步网络据说能极大的提高网络server的连接速度,所以打算写一个专题,来学习和了解异步网络.因为python有个非常出名的异步lib:twisted,所以就用python来完成. 

ok,首先写一个pythone socket的server段,对开放三个端口:10000,10001,10002.krondo的例子中是每个server绑定一个端口,测试的时候需要分别开3个shell,分别运行.这太麻烦了,就分别用三个thread来运行这些services. 

import optparseimport osimport socketimport timefrom threading import Threadimport StringIO txt = '''1111222233334444''' def server(listen_socket):    while True:        buf = StringIO.StringIO(txt)        sock, addr = listen_socket.accept()        print 'Somebody at %s wants poetry!' % (addr,)        while True:                try:                    line = buf.readline().strip()                    if not line:                        sock.close()                        break                    sock.sendall(line)  # this is a blocking call                    print 'send bytes to client:%s' % line                    #sock.close()                except socket.error:                    sock.close()                    break                time.sleep(1)  #server和client连接后,server会故意每发送一个单词后等待一秒钟后再发送另一个单词  def main():    ports = [10000, 10001, 10002]    for port in ports:        listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        addres = (str('127.0.0.1'), port)        listen_socket.bind(addres)        listen_socket.listen(5)        print "start listen at:%s" % (port,)        worker = Thread(target = server, args = [listen_socket])        worker.setDaemon(True)        worker.start()  if __name__ == '__main__':    main()    while True:        time.sleep(0.1) #如果不sleep的话,CPU会被Python完全占用了        pass

登录后复制

下面是一个client,没有才用异步网络,连接这个三个端口的server: 

import socket  if __name__ == '__main__':    ports = [10000, 10001, 10002]    for port in ports:        address = (str('127.0.0.1'), port)        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        sock.connect(address)        poem = ''        while True:            data = sock.recv(4)            if not data:                sock.close()                break            poem += data        print poem

登录后复制

下面用异步的client来读取,代码如下: 

import datetime, errno, optparse, select, socket def connect(port):    """Connect to the given server and return a non-blocking socket."""    address = (str('127.0.0.1'), port)    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    sock.connect(address)    sock.setblocking(0)    return sock def format_address(address):    host, port = address    return '%s:%s' % (host or '127.0.0.1', port) if __name__ == '__main__':    ports = [10000, 10001, 10002]    start = datetime.datetime.now()     sockets = map(connect, ports)    poems = dict.fromkeys(sockets, '') # socket -> accumulated poem      # socket -> task numbers    sock2task = dict([(s, i + 1) for i, s in enumerate(sockets)])    sockets = list(sockets) # make a copy     while sockets:        #运用select来确保那些可读取的异步socket可以立即开始读取IO        #OS不停的搜索目前可以read的socket,有的话就返回rlist        rlist, _, _ = select.select(sockets, [], [])        for sock in rlist:            data = ''            while True:                try:                    new_data = sock.recv(1024)                except socket.error, e:                    if e.args[0] == errno.EWOULDBLOCK:                        break                    raise                else:                    if not new_data:                        break                    else:                        print new_data                        data += new_data             task_num = sock2task[sock]            if not data:                sockets.remove(sock)                sock.close()                print 'Task %d finished' % task_num            else:                addr_fmt = format_address(sock.getpeername())                msg = 'Task %d: got %d bytes of poetry from %s'                print  msg % (task_num, len(data), addr_fmt)             poems[sock] += data     elapsed = datetime.datetime.now() - start    print 'Got poems in %s' %  elapsed

登录后复制

结果只需要4秒就完成了读取任务。效率是刚才同步socket的三倍。对客户端的异步改造主要有两点: 

同步模式下,客户端分别创建socket;而在异步模式下,client开始就创建了所有的socket。

立即学习“Python免费学习笔记(深入)”;

通过“sock.setblocking(0)”设置socket为异步模式。

通过Unix系统的select俩返回可读取IO

最为核心的是26行和29行。尤其是29行的select操作返回待读取socket的列表。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2281637.html

(0)
上一篇 2025年2月27日 18:48:52
下一篇 2025年2月25日 17:22:51

AD推荐 黄金广告位招租... 更多推荐

发表回复

登录后才能评论