socket__简单服务
https://www.cnblogs.com/zhiyong-ITNote/p/7553694.html =====>>>>> 这个是详细网址
'''
要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值。
select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接收所有要发出去的data(outgoing data),第3个监控错误信息
在网上一直在找这个select.select的参数解释, 但实在是没有, 哎...自己硬着头皮分析了一下。
readable, writable, exceptional = select.select(inputs, outputs, inputs)
select 函数的参数其实很好理解, 前提是我们对unix 网络编程有了解. select 模型是unix 系统中的网络模型, python 将其封装了,因此我们使用起来就比较方便, 但是面试官就不会这么觉得了(最近被面试逼疯了, 考虑问题都从面试官的角度考虑), 先说下unix 系统中的select 模型吧, 参数原型:
int select(int maxfdpl, fd_set * readset, fd_set *writeset, fd_set *exceptset, const struct timeval * tiomeout)
'''
import socket import select sk=socket.socket() sk.bind(("127.0.0.1",8001)) sk.listen(5) inputs=[sk,] outputs=[] while True: rlist,wlist,e=select.select(inputs,outputs,[],1)
print(len(inputs),len(rlist),len(outputs),len(wlist)) #rlist中是socket 对象列表 【sk】
#打印的第一个参数是 公有多少个连接,2,变化的rlist个数, 3,有操作变化个数,4,也是有操作变化个数
for i in rlist: #循环这个句柄,只要inputs,有变化,rlist就能取到
if i == sk: #判断是否相等sk,相等话证明就会有新的连接 conn,addr=i.accept() #然后建立连接 inputs.append(conn) #把此次连接的线路也进行监听 conn.sendall(bytes("hello",encoding="utf8")) #发送给客户端一个信息验证 else: #如果不等,就有可能是线路发生了变化 try: #程序运行正确 data=i.recv(1024) #接收客户端信息 print(data.decode()) if not data: # raise Exception("断开连接") else: #一些运行正常 ,把此次线路变化加到outputs列表中 outputs.append(i) except Exception as e: #如果有程序退出, 也需要把此次线路变化从监听中删除 print(e) inputs.remove(i)
for s in writable: try: # 如果消息队列中有消息,从消息队列中获取要发送的消息 message_queue = message_queues.get(s) send_data = '' if message_queue is not None: send_data = message_queue.get_nowait() else: # 客户端连接断开了 print "has closed " except Queue.Empty: # 客户端连接断开了 print "%s" % (s.getpeername()) outputs.remove(s) else: # print "sending %s to %s " % (send_data, s.getpeername) # print "send something" if message_queue is not None: s.send(send_data) else: print "has closed " # del message_queues[s] # writable.remove(s) # print "Client %s disconnected" % (client_address) # # Handle "exceptional conditions" # 处理异常的情况 for s in exceptional: print ('exception condition on', 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] sleep(1)
其实select, 并不是真正实现并发,一直循环着(串行)在监听数据是否有变化,并把数据处理完毕之后才会去处理新的请求数据。如果每个请求的耗时比较长时,select版本的服务器端也无法完成同时操作,这种模式称之为伪并发。
PS: 能检测所有的IO操作,不单纯是socket, 但是文件操作除外。
select 系统内核底层维护了一个for循环,检测变化。在windows、linux平台都可以用,支持跨平台。有C10K问题,最大支持1024个
poll, 底层也是通过for循环实现。 但是没有个数限制了。但是for循环效率不高。
epoll,谁变化(回调函数),告诉epoll谁发生了变化。

浙公网安备 33010602011771号