python select的使用

Posted 晴天小猫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python select的使用相关的知识,希望对你有一定的参考价值。

使用异步io实现只使用单进程,单线程的socket。处理多个用户的请求。
 
先简单说明一下select异步io工作原理:
 
select 是一个跨平台的异步io模型,由于我们计算机的硬盘速度,远远低于我们内存的速度,因此如果同时有多个用户来请求数据时候,io效率就会变得更慢。
而select 是一直不断在监控我们网络接口的。如果我们的服务器网络接收到,一个用户的请求,就会在系统的某个路径下面,生成一个文件描述符,select就是不断的在监控这些文件描述符(即每个用户的连接),如果连接进来了,就会调用内核将这个文件描述符标志位改为ready,从而我们的select就可以操作这文件描述符了。
回到我们的程序上来,异步的socket 使用select 就是一直在循环,不断的去监视文件描述符,当有新的用户来连接时候,直接把新连接的用户保存到一个列表当中。如果循环到不是新的用户则对用户的操作进行处理
socket 服务器端
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
 
import select
import socket
import sys
import Queue
 
# Create a TCP/IP socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(False)
 
# Bind the socket to the port
server_address = (‘localhost‘, 10000)
print(sys.stderr, ‘starting up on %s port %s‘ % server_address)
server.bind(server_address)
 
# Listen for incoming connections
server.listen(5)
 
# Sockets from which we expect to read
inputs = [server]
 
# Sockets to which we expect to write
outputs = []
 
message_queues = {}
while inputs:
 
    # Wait for at least one of the sockets to be ready for processing
    print(‘\nwaiting for the next event‘)
    readable, writable, exceptional = select.select(inputs, outputs, inputs)
    # Handle inputs
    for s in readable:
 
        if s is server:
            # A "readable" server socket is ready to accept a connection
            connection, client_address = s.accept()
            print(‘new connection from‘, client_address)
            connection.setblocking(False)
            inputs.append(connection)
 
            # Give the connection a queue for data we want to send
            message_queues[connection] = Queue.Queue()
        else:
            data = s.recv(1024)
            if data:
                # A readable client socket has data
                print(sys.stderr, ‘received "%s" from %s‘ % (data, s.getpeername()))
                message_queues[s].put(data)
                # Add output channel for response
                if s not in outputs:
                    outputs.append(s)
            else:
                # Interpret empty result as closed connection
                print(‘closing‘, client_address, ‘after reading no data‘)
                # Stop listening for input on the connection
                if s in outputs:
                    outputs.remove(s)  # 既然客户端都断开了,我就不用再给它返回数据了,所以这时候如果这个客户端的连接对象还在outputs列表中,就把它删掉
                inputs.remove(s)  # inputs中也删除掉
                s.close()  # 把这个连接关闭掉
 
                # Remove message queue
                del message_queues[s]
    # Handle outputs
    for s in writable:
        try:
            next_msg = message_queues[s].get_nowait()
        except Queue.Empty:
            # No messages waiting so stop checking for writability.
            print(‘output queue for‘, s.getpeername(), ‘is empty‘)
            outputs.remove(s)
        except KeyError:
            continue
        else:
            print(‘sending "%s" to %s‘ % (next_msg, s.getpeername()))
            s.send(next_msg)
    # Handle "exceptional conditions"
    for s in exceptional:
        print(‘handling exceptional condition for‘, s.getpeername())
        # Stop listening for input on the connection
        inputs.remove(s)
        if s in outputs:
            outputs.remove(s)
        s.close()
 
        # Remove message queue
        del message_queues[s]
 
 
socket 客户端:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = ‘admin‘
import socket
import sys
 
def select_sock(ip, port):
    msg = u‘俺老孙来也!‘.encode(‘utf-8‘)
    sock = [socket.socket(socket.AF_INET,socket.SOCK_STREAM),
            socket.socket(socket.AF_INET,socket.SOCK_STREAM),
            socket.socket(socket.AF_INET,socket.SOCK_STREAM),
            socket.socket(socket.AF_INET,socket.SOCK_STREAM),
            socket.socket(socket.AF_INET,socket.SOCK_STREAM),
            socket.socket(socket.AF_INET,socket.SOCK_STREAM),
            socket.socket(socket.AF_INET,socket.SOCK_STREAM),
            ]
    for s in sock:
        s.connect((ip, port))
        s.send(msg)
        print >> sys.stderr ,‘%s  send :%s‘ % (s.getpeername(), msg)
    for i in sock:
        data = i.recv(1024)
        print >> sys.stderr, ‘%s recv:%s ‘ % (i.getpeername(), data)
        if not data:
            print >> sys.stderr, ‘connect close!‘, i.getpeername()
if __name__ == ‘__main__‘:
    server_addr = ‘192.168.1.111‘
    server_port = 2288
    select_sock(server_addr, server_port)

以上是关于python select的使用的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中的mysql中使用带有变量的select语句

python python中的套接字服务器使用select函数

python_select 与 fink 安装的 python?

Python网络编程中的select 和 poll I/O复用的简单使用

使用mysql在python中的while循环中进行SELECT

如何在 python asyncio 中等待 select.select 调用