zoukankan      html  css  js  c++  java
  • 【Pyhton Network】使用poll()或select()实现非阻塞传输

    通常情况下,socket上的I/O会阻塞。即除非操作结束,否则程序不会照常进行。而以下集中情况需要在非阻塞模式下进行:
    1. 网络接口在等待数据时是活动的,可以做出相应;
    2. 在不使用线程或进程的情况下也可以同时处理多个网络相关任务;
    3. 在网络上等待的时候可以执行其它计算
    在以上情况中,可以使用两个标准工具解决,poll和select。它们都可以通知操作系统哪个socket对程序感兴趣,当该socket上有事件发生时,操作系统才调用处理程序。
    服务器程序每隔5秒向连接对象发送系统当前时间,如下:

    #! /usr/bin/env python
    # Delaying Server - Chapter 5 - delayserver.py
    
    import socket, traceback, time
    
    host = ''        # Bind to all interface
    port = 51423
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((host, port))
    s.listen(1)
    
    while 1:
        try:
            clientsock, clientaddr = s.accept()
        except KeyboardInterrupt:
            raise
        except:
            traceback.print_exc()
            continue
        
        # Process the connection
        try:
            print "Got Connection from ", clientsock.getpeername()
            while 1:
                try:
                    clientsock.sendall(time.asctime() + "
    ")    
                except:
                    break
                time.sleep(5)
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            traceback.print_exc()
    
        # Close the connection
    
        try:
            clientsock.close()
        except KeyboardInterrupt:
            raise
        except:
            traceback.print_exc()
    View Code

    poll客户端程序如下:

    #! /usr/bin/env python
    # Nonblocking I/O - Chapter 5- pollclient.py
    
    import socket, sys, select
    
    host = "localhost"
    port = 51423
    
    spinsize = 10
    spinpos = 0
    spindir = 1
    
    def spin():
        global spinsize, spinpos, spindir
        spinstr = '.'*spinpos + '|' + '.'*(spinsize-spinpos-1)    
        sys.stdout.write('
    '+spinstr+' ')
        sys.stdout.flush()
        
        spinpos += spindir
        if spinpos < 0:
            spindir = 1
            spinpos = 1
        elif spinpos >= spinsize:
            spinpos -= 2
            spindir = -1
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.connect((host, port))
    
    p = select.poll()
    p.register(s.fileno(), select.POLLIN | select.POLLERR | select.POLLHUP)
    while 1:
        results = p.poll(50)
        if len(results):
            if results[0][1] == select.POLLIN:
                data = s.recv(4096)
                if not len(data):
                    print "
    Remote en closed connection; exiting."
                    break
                # Only one item in here -- if there's anything, it's for me
                sys.stdout.write("
    Received: "+data)
                sys.stdout.flush()
            else:
                print "
    Problem occured; exiting."    
                sys.exit(0)
        spin()
    View Code

    等价的,select客户端如下:

    #! /usr/bin/env python
    # Nonblocking I/O with select() - Chapter 5 - selectclient.py
    
    import socket, sys, select
    
    host = 'localhost'
    port = 51423
    
    spinsize = 10
    spinpos = 0
    spindir = -1
    
    def spin():
        global spinsize, spinpos, spindir
        spinstr = '.'*spinpos + '|' + '.'*(spinsize-spinpos-1)
        sys.stdout.write('
    '+spinstr+' ')
        sys.stdout.flush()
    
        spinpos += spindir
        if spinpos < 0:
            spinpos = 1
            spindir = 1
        elif spinpos >= spinsize:
            spinpos -= 2
            spindir = -1
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.connect((host, port))
    
    while 1:
        infds, outfds, errfds = select.select([s], [], [s], 0.05) # [s] just the same as[s.fileno()], only need to be a list.
        if len(infds):
            # Normally, one would use something like "for fd in infds" here.
            # We don't bother since there will only ever be a single file
            # descriptor here.
            data = s.recv(4096)
            if not len(data):
                print "
    Remote and closed connection; exiting."
                break
            # Only one item in here -- if there's anything, it's for us.
            sys.stdout.write("
    Received: "+data)
            sys.stdout.flush
        if len(errfds):
            print "
    Problem occurred; exiting."
            sys.exit(0)
        spin()
            
            
    View Code

    运行截图如下:

  • 相关阅读:
    1208C Magic Grid
    jsc2019_qualE Card Collector
    jsc2019_qualD Classified
    jsc2019_qualC Cell Inversion
    牛客提高D6t3 分班问题
    牛客提高D6t2 破碎的序列
    牛客提高D6t1 积木大赛
    loj6259「CodePlus 2017 12 月赛」白金元首与独舞
    p4208 [JSOI2008]最小生成树计数
    p4111 [HEOI2015]小Z的房间[简述矩阵树定理]
  • 原文地址:https://www.cnblogs.com/bombe1013/p/3593332.html
Copyright © 2011-2022 走看看