Python select 
  Python的select()方法直接调用操作系统的IO接口,它监控sockets,open files, and pipes(所有带fileno()方法的文件句柄)何时变成readable 和writeable, 或者通信错误,select()使得同时监控多个连接变的简单,并且这比写一个长循环来等待和监控多客户端连接要高效,因为select直接通过操作系统提供的C的网络接口进行操作,而不是通过Python的解释器。
注:使用Python的文件对象选择()为Unix工作,但在Windows下不支持。
 
select实现socketserver
注:接下来通过echo server例子要以了解select 是如何通过单进程实现同时处理多个非阻塞的socket连接的
注:必须在非阻塞情况下。
 
服务端:
import select
import socket
import queue server = socket.socket()
server.bind(('localhost' ,9000))
server.listen(1000) # 设置非阻塞模式
server.setblocking(False)
msg_dic = {} # 内核检测并发链接
inputs = [server,] # outputs存放链接需要返回的数据
outputs = [] # 为了循环调入select加入while
while True: # 1,需要内核检测哪些链接,有一个活动就返回所有链接循环。
# 2,处理返回数据。
# 3,如果有并发的链接断开,内核会返回报错到inputs内,有哪几个有问题。
# 有链接进入会返回三个数据:
# readable:返回一个列表,活动的,可读数据的
# writeable:存放需要返回的数据。
# exceptional:返回出现异常的活动链接
readable,writeables,exceptional = select.select(inputs,outputs,inputs)
print(readable,writeables,exceptional) # 收处理
for r in readable:
# 代表来了一个新连接
if r is server: # 等待客户端生成实例
conn,addr = server.accept() # 打印客户端IP地址
print("来了个新连接",addr) # 因为这个新建里的链接还没发数据过来,现在就收数据的话程序就报错了
#所以要想实现客户端发数据来时server端能知道,就需要让select在检测这
#个conn。
inputs.append(conn) # 初始化一个队列,后面存要返回这个客户端的数据
msg_dic[conn] = queue.Queue() # 接收新连接数据
else:
# 获取数据
data = r.recv(1024)
# 打印数据
print("收到数据:",data) # 将返回的数据排列到队列中
msg_dic[r].put(data) # 放入返回的链接队列
outputs.append(r) # 发数据:要返回给客户端的链接列表
for w in writeables:
# 重链接列表中取出队列的实例
data_to_client = msg_dic[w].get()
# 返回给客户端数据
w.send(data_to_client)
# 确保下次循环的时候writeable,不返回这个已经处理完的链接
outputs.remove(w) # 删除:错误链接
for e in exceptional:
# 查找错误链接是否存在outputs
if e in outputs:
# 如果有就删除错误链接
outputs.remove(e)
# 删除inputs下的错误链接
inputs.remove(e)
# 删除队列中的错误链接
del msg_dic[e]

客户端:

import socket
client = socket.socket()
#client.connect(('192.168.1.177',9999))
client.connect(('localhost',9000))
while True:
msg = input(">>:").strip()
if len(msg) == 0:continue
client.send(msg.encode("utf-8"))
data = client.recv(1024)
print("recv:",data.decode())
client.close()
select实现socketserver并发(完整版)
import select
import socket
import sys
import queue server = socket.socket()
server.setblocking(0) server_addr = ('localhost',10000) print('starting up on %s port %s' % server_addr)
server.bind(server_addr) server.listen(5) inputs = [server, ] #自己也要监测呀,因为server本身也是个fd
outputs = [] message_queues = {} while True:
print("waiting for next event...") readable, writeable, exeptional = select.select(inputs,outputs,inputs) #如果没有任何fd就绪,那程序就会一直阻塞在这里 for s in readable: #每个s就是一个socket if s is server: #别忘记,上面我们server自己也当做一个fd放在了inputs列表里,传给了select,如果这个s是server,代表server这个fd就绪了,
#就是有活动了, 什么情况下它才有活动? 当然 是有新连接进来的时候 呀
#新连接进来了,接受这个连接
conn, client_addr = s.accept()
print("new connection from",client_addr)
conn.setblocking(0)
inputs.append(conn) #为了不阻塞整个程序,我们不会立刻在这里开始接收客户端发来的数据, 把它放到inputs里, 下一次loop时,这个新连接
#就会被交给select去监听,如果这个连接的客户端发来了数据 ,那这个连接的fd在server端就会变成就续的,select就会把这个连接返回,返回到
#readable 列表里,然后你就可以loop readable列表,取出这个连接,开始接收数据了, 下面就是这么干 的 message_queues[conn] = queue.Queue() #接收到客户端的数据后,不立刻返回 ,暂存在队列里,以后发送 else: #s不是server的话,那就只能是一个 与客户端建立的连接的fd了
#客户端的数据过来了,在这接收
data = s.recv(1024)
if data:
print("收到来自[%s]的数据:" % s.getpeername()[0], data)
message_queues[s].put(data) #收到的数据先放到queue里,一会返回给客户端
if s not in outputs:
outputs.append(s) #为了不影响处理与其它客户端的连接 , 这里不立刻返回数据给客户端 else:#如果收不到data代表什么呢? 代表客户端断开了呀
print("客户端断开了",s) if s in outputs:
outputs.remove(s) #清理已断开的连接 inputs.remove(s) #清理已断开的连接 del message_queues[s] ##清理已断开的连接 for s in writeable:
try :
next_msg = message_queues[s].get_nowait() except queue.Empty:
print("client [%s]" %s.getpeername()[0], "queue is empty..")
outputs.remove(s) else:
print("sending msg to [%s]"%s.getpeername()[0], next_msg)
s.send(next_msg.upper()) for s in exeptional:
print("handling exception for ",s.getpeername())
inputs.remove(s)
if s in outputs:
outputs.remove(s)
s.close() del message_queues[s]

Python select实现socket并发的更多相关文章

  1. python select解析 socket高效通信服务器 自己写的socketserver

    import select import socket import queue server = socket.socket()#创建服务器端 server.bind(('localhost',99 ...

  2. Python selectors实现socket并发

    selectors模块 此模块允许基于选择模块原语构建高级别和高效的I / O多路复用. 鼓励用户使用此模块,除非他们想要精确控制使用的os级别的原语. 注:selectors也是包装了select高 ...

  3. 利用select实现伪并发的socket

    使用socket模块可以实现程序之间的通信,但是server在同一时刻只能和一个客户端进行通信,如果要实现一个server端可以和多个客户端进行通信可以使用 1.多线程 2.多进程 3.select ...

  4. python全栈开发从入门到放弃之socket并发编程之协程

    一.为什么会有协程 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情 ...

  5. python基础-11 socket,IO多路复用,select伪造多线程,select读写分离。socketserver源码分析

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  6. 基于select类型多路IO复用,实现简单socket并发

    还有很多缺限,如客户断开无限重复 以下转至老师博客: server: #!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = " ...

  7. python全栈开发从入门到放弃之socket并发编程之IO模型

    一 IO模型介绍 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问 ...

  8. Day8 - Python网络编程 Socket编程

    Python之路,Day8 - Socket编程进阶   本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台 ...

  9. python select epoll poll的解析

    select.poll.epoll三者的区别 select select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组(在linux中一切事物皆文件 ...

随机推荐

  1. Linux下的awk文本分析命令实例(一)

    1.  入门实例1.1 显示最近登录的5个帐号: [root@localhost ~]# | awk '{print $1}' root root root root reboot 1.2 如果只是显 ...

  2. OpenJDK和JDK区别

    OpenJDK和JDK区别 OpenJDK与JDK的区别分析 Sun的JDK7.OpenJDK及IcedTea释疑 简介(ps): 简单来说jdk从7开始,弄出一个可以自由使用的公共版本(openjd ...

  3. Linux 的基本操作(系统用户及用户组的管理)

    [认识/etc/passwd和/etc/shadow] 这两个文件可以说是linux系统中最重要的文件之一.如果没有这两个文件或者这两个文件出问题,则你是无法正常登录linux系统的. /etc/pa ...

  4. meat标签

    1.文档兼容模式的定义 Edge 模式告诉 IE 以最高级模式渲染文档,也就是任何 IE 版本都以当前版本所支持的最高级标准模式渲染,避免版本升级造成的影响.简单的说,就是什么版本 IE 就用什么版本 ...

  5. 向comboboxEdit中动态添加数据库中保存的用户自定义单位制的名称

    if (radioGroup1.SelectedIndex == 2) { bool _Flag = true; sm.SetLciVisible(lciDelete, _Flag); sm.SetL ...

  6. windows安装tomcat

    1.打开官网http://tomcat.apache.org/ 2.在左侧的导航栏Download下方选择最新的Tomcat 9,点击页面下方的“ 64-bit Windows zip (pgp, m ...

  7. GCD与LCM

    求最大公约数(GCD)和求最小公倍数(LCM): 首先是求最大公约数,我们可以利用辗转相除法来求 1 int gcd(int a,int b) 2 { 3 if(b==0) 4 return a; 5 ...

  8. tcpdf开发文档(中文翻译版)

    2017年5月3日15:06:15 这个是英文翻译版,我看过作者的文档其实不太友善或者不方便阅读,不如wiki方便 后面补充一些,结构性文档翻译 这是一部官方网站文档,剩余大部分都是开发的时候和网络总 ...

  9. 查看Sql Server 数据库的内存使用情况

    -- 查询SqlServer总体的内存使用情况 select type , sum(virtual_memory_reserved_kb) VM_Reserved , sum(virtual_memo ...

  10. Linux Shell编程中的几个特殊符号命令 & 、&& 、 ||

    https://blog.csdn.net/hack8/article/details/39672145 Linux Shell编程中的几个特殊符号命令 & .&& . || ...