Python 비동기 네트워크 탐색

巴扎黑
풀어 주다: 2016-12-09 13:35:20
원래의
1520명이 탐색했습니다.

비동기 네트워크는 네트워크 서버의 연결 속도를 크게 향상시킬 수 있다고 하는데, 비동기 네트워크를 배우고 이해하기 위한 주제를 작성하려고 합니다. Python에는 매우 유명한 비동기 Lib: Twisted가 있어서 Python을 사용하여 완성했습니다.

좋아요, 먼저 pythone 소켓의 서버 세그먼트를 작성하고 10000, 10001, 10002의 3개 포트를 엽니다. krondo의 예에서 각 서버는 테스트 중에 3개의 셸을 열어야 합니다. 각각 별도로 실행하는 것은 너무 번거롭기 때문에 이러한 서비스를 실행하려면 3개의 스레드를 사용하세요.

import optparse
import os
import socket
import time
from threading import Thread
import StringIO
 
txt = '''1111
2222
3333
4444
'''
 
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
로그인 후 복사

다음은 비동기 네트워크가 없는 경우 3개의 포트로 서버에 연결합니다.

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
로그인 후 복사

읽기에는 비동기 클라이언트가 사용됩니다. 코드는 다음과 같습니다.

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초밖에 걸리지 않습니다. 효율성은 현재 동기화 소켓의 3배입니다. 클라이언트의 비동기 변환에는 두 가지 주요 사항이 있습니다.

동기 모드에서는 클라이언트가 소켓을 별도로 생성하고, 비동기 모드에서는 클라이언트가 처음부터 모든 소켓을 생성합니다.

"sock.setblocking(0)"을 통해 소켓을 비동기 모드로 설정합니다.

Unix 시스템 중 두 가지 선택을 통해 읽을 수 있는 IO를 반환합니다

가장 핵심적인 것은 26행과 29행입니다. 특히 29행의 선택 작업은 읽을 소켓 목록을 반환합니다.


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿