• PYTHON__关于Socket中的Select使用理解


    关于Socket中的Select使用理解

    以下是代码和中文注释的个人理解

    import socket, select, Queue
    
    server=('192.168.2.100',10086)
    
    #创建TCP/TP Socket
    sock_ser=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #设置不阻塞监听
    sock_ser.setblocking(False)
    sock_ser.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    #绑定IP地址
    sock_ser.bind(server)
    #监听连接
    sock_ser.listen(10)
    
    #准备用来读取数据的Socket,客户端向服务端的读端口写
    incomes=[sock_ser]
    #准备用来写的Socket,客户端从写Socket读
    outputs=[]
    
    """
    写出消息的队列,由于select是循环机制,所以每个独立的outputs都需要一个队列来保存待写出的数据,
    等到轮回到自己的时候写出
    """
    msg_que={}
    
    #超时时间。
    timeout=20
    
    #服务端的Socket用来接受服务端的连接,并用作与循环。
    while incomes:
        """
        先等待至少一个Socket的数据处理,Select返回当前三个列表。
        这三个数据来自于可读,可写,返回的错误。
        Select监听并等待网络活动。如果有网络活动则开始执行
        """
        rs,ws,es=select.select(incomes,outputs,incomes,timeout)
        if not(rs or ws or es):
            print "error: timeout...."
            break
        for s in rs:
            """
            此处的rs存储很多Socket,
            开始存储只有服务端本身的Socket,用于与客户端建立新的连接。并将客户端建立好的连接存储在incomes中,incomes会返回给rs。
            存储的的客户端,会被用于收发数据。
            """
            #rs队列中按个读取,如果是服务端的socket就用那个与建立新的连接。
            if s is sock_ser:
                conn,addr=s.accept()
                print "connect by  ",addr
                conn.setblocking(False)
                incomes.append(conn)
                #为接入的客户端提供一个队列来发送回复给客户端的数据
                msg_que[conn]=Queue.Queue()
            #如果不是服务端的socket,是客户端建立连接的Socket,就收数据,并判断是否断开。
            else:
                data=s.recv(1024)
                #有数据就收数据
                if data:
                    print "receive client ",data
                    msg_que[s].put(data)
                    if s not in outputs:
                        outputs.append(s)
                #可读的socket没有数据发送,则说明客户端断开连接,我们删除这个客户端。
                else:
                    if s in outputs:
                        outputs.remove(s)
                    incomes.remove(s)
                    s.close()
                    del msg_que[s]
        #写操作,查看队列里面是否有东西,并发送到对应的Socket.
        for s in ws:
            try:
                msg = msg_que[s].get_nowait()
            except Queue.Empty:
                #因为是轮回的,当前面连接断开后,写的socket尚未删除,这一步还是要执行的,所以最后输出了几个EMPTY。
                print 'msg empty'
                outputs.remove(s)
            else:
                s.send("from server :"+msg)
        for s in es:
            print "except",s.getpeername()
            if s in incomes:
                incomes.remove(s)
            if s in outputs:
                outputs.remove(s)
            s.close()
            del msg_que[s]
    

      

  • 相关阅读:
    配置java 环境变量(jdk)
    R语言的神奇之一--基于向量
    python绘制图形(Turtle模块)
    右键菜单中新建记事本选项丢失的解决办法
    在windows下远程访问linux服务器
    针对Chrome谷歌等浏览器不再支持showModalDialog的解决方案
    导入一个新项目需要注意的几大问题(jdk1.6+eclipse4.4+tomcat6)
    【漏洞公告】Tomcat信息泄漏和远程代码执行漏洞:CVE-2017-12615/CVE-2017-12616
    python基础篇10-py2和py3编码
    python基础篇03-range/for/break/continue/while/if
  • 原文地址:https://www.cnblogs.com/freeideas/p/3050255.html
Copyright © 2020-2023  润新知