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]

  

posted @ 2013-04-29 01:01  freeidea  阅读(619)  评论(0编辑  收藏  举报