首页 > 代码库 > python select和socket配合使用基础学习,是python标准库例子

python select和socket配合使用基础学习,是python标准库例子

# -*- coding: utf-8 -*-

# python:2.x

__author__ = ‘Administrator‘

import select,socket,sys,Queue

#作用:等待输入或者输出通道已经准备就绪的通知

#select模块允许访问特定平台的IO监视函数,可移植接口是POSIX函数select(),unixwindows都支持这个函数,poll()只支持unix,还有一些适用于unix特定变种选项

#select()是底层操作系统实现一个直接接口,会监视套接字,打开文件和管道(可以是任何有filen()方法对象,它会返回一个合法的文件描述符),这个是可读,可写的,或者出现一个通信错误,select()可以高效的同时监视多个连接

#select()服务器端例子学习

serve=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

serve.setblocking(0)#如果套接字为0,设置为非阻塞,阻塞模式

serer_address=(‘localhost‘,10000)

print >>sys.stderr,‘starting up on%s port %s‘%serer_address

serve.bind(serer_address)

serve.listen(5)

"""

select()原型是(rlist,wlist,xlist[,timeout])

rlist等待读取对象,wlist等待定稿对象,xlist等待异常对象,最后一个可选对象,指定等待时间,单位是s,select()方法返回值准备好的对象是三元组,若在timeout时间内,没有对象准备好,那么返回值是空的列表

"""

inputs=[serve]#读取

outputs=[]#写入

#服务器主循环向这些列表添加或者删除连接,由于版本服务器在发送数据之前要等待一个套接字变为可写(不是马上发出相应),所以每个输出连接都需要一个队列,作为通过这个套接字发送的数据缓冲区

message_queues={}

#服务器程序主要部分是循环,调用 select()来阻塞,并等待网络活动

while inputs:

    print >>sys.stderr,‘waiting for the next event‘

    readable,writable,exceptional=select.select(inputs,outputs,inputs)

    #可读的套接字表示3种可能情况,如果套接字是主服务器套接字,即用来监听连接的套接字,意味它已经准备就绪,可以接受另一个到来的连接,除了将新连接添加到要监视的输入列表之外,这一部分还将客户端设置为非阻塞

    for s in readable:

        if s is serve:

            connectiuon,client_addre=s.accept()

            print >>sys.stderr,‘connection from‘,client_addre

            connectiuon.setblocking(0)

            inputs.append(connectiuon)

            message_queues[connectiuon]=Queue.Queue()

            #下一种情况是已经连接了,客户已经发数据,数据使用recv()读取,然后旋转在队列中,进行返回

        else:

            data=http://www.mamicode.com/s.recv(1024)

            if data:

                print >>sys.stderr,‘received%s form %s‘%(data,s.getpeername())

                message_queues[s].put(data)

                if s not in outputs:

                    outputs.append(s)

                #没有数据可用的可读套接字来自已经断开连接端,可以关闭流

                else:

                    print >>sys.stderr,‘closeing‘,client_addre

                    if s in outputs:

                        outputs.append(s)

                    inputs.append(s)

                    s.close()

 

                    del message_queues[s]

        #对于可写连接,情况要少一些,如果对应一个连接队列中有数据,则发送下一个消息,否则,将这个连接从输出连接删除,下一次循环,select()不再指示这个套接字已经准备就绪发送数据

        for s in writable:

            try:

                next_msg=message_queues[s].get_nowait()

            except Queue.Empty:

                print >>sys.stderr,‘ ‘,s.getpeername(),‘queue empty‘

                outputs.remove(s)

            else:

                print >>sys.stderr,‘ sending %s to %s‘%(next_msg,s.getpeername())

                s.send(next_msg)

        #最后,如果一个套接字有错误,则关闭

        for s in exceptional:

            print >>sys.stderr,‘exception condition on‘,s.getpeername()

            inputs.remove(s)

            if s in outputs:

                outputs.remove(s)

            s.close()

 

#select()客户端程序

message=[‘this is the message‘,‘it will be sent,‘

                               ‘in parts.‘]

serer_address=(‘localhost‘,10000)

socks=[socket.socket(socket.AF_INET,socket.SOCK_STREAM),

       socket.socket(socket.AF_INET,socket.SOCK_STREAM),]

print >>sys.stderr,‘connection to%s and %s‘%(serer_address)

for s in socks:

    s.connect(serer_address)

#通过各个套接字发送一次信息,写新数据之后再得到所有相应数据

for m in message:

    if s in socks:

        print >>sys.stderr,‘%s:sending%s‘%(s.getsockname(),m,s.send(m))

 

for s in socks:

    data=http://www.mamicode.com/s.recv(1024)

    print ‘%s:%s‘%(s.getpeername(),data)

    if not data:

        print >>sys.stderr,‘closeing socket‘,s.getsockname()

        s.close()

python select和socket配合使用基础学习,是python标准库例子