您现在的位置是:主页 > news > 网站建设基本流程包括/百度做广告多少钱

网站建设基本流程包括/百度做广告多少钱

admin2025/6/15 20:55:47news

简介网站建设基本流程包括,百度做广告多少钱,wordpress session,如何创建自己的网站链接一、前言 之前我们讲了select、poll、epoll的介绍,我们今天先来说说select的IO多路复用代码实现。我们先来根据之前图说说select的原理。 这边多说了,想了解更多:猛击这里 二、select的代码实现 Python的select()方法直接调用操作系统的IO接口…

网站建设基本流程包括,百度做广告多少钱,wordpress session,如何创建自己的网站链接一、前言 之前我们讲了select、poll、epoll的介绍,我们今天先来说说select的IO多路复用代码实现。我们先来根据之前图说说select的原理。 这边多说了,想了解更多:猛击这里 二、select的代码实现 Python的select()方法直接调用操作系统的IO接口…

一、前言

  之前我们讲了select、poll、epoll的介绍,我们今天先来说说select的IO多路复用代码实现。我们先来根据之前图说说select的原理。

  这边多说了,想了解更多:猛击这里

二、select的代码实现

  Python的select()方法直接调用操作系统的IO接口,它监控sockets,open files, and pipes(所有带fileno()方法的文件句柄)何时变成readable 和writeable, 或者通信错误,select()使得同时监控多个连接变的简单,并且这比写一个长循环来等待和监控多客户端连接要高效,因为select直接通过操作系统提供的C的网络接口进行操作,而不是通过Python的解释器。

  注意:Using Python’s file objects with select() works for Unix, but is not supported under Windows.

2.1、select实现非阻塞连接

说明:通过select是非阻塞的,accept和recive都不阻塞了,没有值就会报错。就是说没有连接就不要让它走server.accept()这一步。让select帮助去检测这个100个连接。所以说只要有连接,有活动了,有数据才去accept。服务端代码如下:

import select,socket
server = socket.socket()
server.bind(("localhost",9000))
server.listen(1000)
server.setblocking(False) #设置为非阻塞
inputs = [server,]  #一开始只有自己的连接,所以一开始把自己的连接发到列表中
outputs = []
while True:#exceptional表示如果inputs列表中出现异常,会输出到这个exceptional中readable,writeable,exceptional = select.select(inputs,outputs,inputs)# print(readable,writeable,exceptional)for r in readable:if r is server:  #代表一个新连接conn,addr = r.accept()print("来了一个新连接",addr)inputs.append(conn) #因为这个新建立的连接还没有发数据过来,现在就接收的话程序就报错了#所以要想实现这个客户端发数据过来时server端能知道,就需要让让select再检测这个connelse:data = r.recv(1024)print("收到数据:",data)r.send(data)print("send done....")

2.2、select用法

select(rlist, wlist, xlist, timeout=None)

  • rlist:读列表
  • wlist:写列表
  • xlist:异常列表

select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接收所有要发出去的data(outgoing data),第3个监控错误信息,接下来我们需要创建2个列表来包含输入和输出信息来传给select()

#读取连接的列表
inputs = [server,] 
#写入连接的列表
outputs = []

这个inputs和outputs是什么鬼?

  打个比方,就是想让内核帮我去检测100个连接,你传给它一个列表,就是需要检测的列表,就是这个inputs,就是说你想有多少检测的连接放在这个列表里面,然后交给select,就相当于交给内核了。

接下来我们看看上述代码中这行代码的用法:

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

select中inputs,outputs这个好理解,那么第三个为什么也是inputs呐?

答:这个的意思是如果我inputs列表中有100个连接,这100个连接中有5个断了,出现了异常,就会输入到exceptional里面去,但是这个100个连接存在inputs里面,所以传入inputs。

2.3、inputs列表解释

  我们知道用select这种方式,服务端收不到数据式不阻塞的,所以只有当客户端发数据的时候,内核通知你收数据,再把它监测列表中的连接,下一次循坏的时候,如果客户端判断这个连接活了,说明就有数据了。

for r in readable:if r is server:  #代表一个新连接conn,addr = r.accept()print("来了一个新连接",addr)inputs.append(conn) #因为这个新建立的连接还没有发数据过来,现在就接收的话程序就报错了#所以要想实现这个客户端发数据过来时server端能知道,就需要让让select再检测这个conn

代码中的这几行说明,如果是新连接的客户端,就把它加入到inputs列表中,交给select去循环监测。

但是这边有一个问题,我如果发现是新的客户端连接,那么我的inputs列表中判断就是已经存在的连接还是server呐?

答:input中已经有一个server了,在加一个连接的话就是inputs=[server,conn],两个有一个返回,有100个活动,就有100个连接conn,但是select给我们作了封装,inputs返回的就是一个,如果是conn活跃了,返回的就是conn,底层返回的还是两个,一个是server,一个是conn。但是select内部已经帮我们循环了一遍了,所以返回的这个时候就是conn,用户有可能是server,也有可能是conn,谁活动说不准。如果活动的是conn,说明客户发送数据过来了,你接收数据就行了,如果是server,代表又来了一个新连接,所以我来一个新连接,我就再建立一个新连接,把这个连接放到这个inputs列表中,如果返回的是conn,我就直接接数据。

三、逻辑图

 

四、IO多路复用升级版

4.1、知识介绍

outputs的功能就是你发给select是什么链接,下次就给你这些链接,这些链接输出到writeable中。

outputs = []readable,writeable,exceptional = select.select(inputs,outputs,inputs)

 把链接发到outputs中,下一次select的时候,outputs就会把它返回,然后我就可以把它发回去。

4.2、升级版代码

说明:就是我不想立刻发给客户端,需要等一会再发给客户端。那我要等到说明时候呐?我先扔到队列中,一会再发,每一个对了连接单独搞一个队列,放到队列中然后实现下一次循环。

import select,socket,queue
server = socket.socket()
server.bind(("localhost",9000))
server.listen(1000)
server.setblocking(False) #设置为非阻塞
msg_dic = dict() #生成一个队列字典
inputs = [server,]  #一开始只有自己的连接,所以一开始把自己的连接发到列表中
outputs = []
while True:#exceptional表示如果inputs列表中出现异常,会输出到这个exceptional中readable,writeable,exceptional = select.select(inputs,outputs,inputs)# print(readable,writeable,exceptional)for r in readable:if r is server:  #代表一个新连接conn,addr = r.accept()print("来了一个新连接",addr)inputs.append(conn)msg_dic[conn] = queue.Queue() #初始化一个队列,后面存要返回给这个客户端的数据else:data = r.recv(1024)print("收到数据:",data)msg_dic[r].put(data)outputs.append(r)# r.send(data)# print("send done....")for w in writeable:  #要返回给客户端的链接列表data_to_client = msg_dic[w].get()w.send(data_to_client)   #返回给客户端的源数据outputs.remove(w)  #确保下次循环的时候writeable,不返回这个已经处理完的这个连接了for e in exceptional:  #处理异常的连接if e in outputs:   #因为e不一定在outputs,所以先要判断outputs.remove(e)inputs.remove(e)   #删除inputs中异常连接del msg_dic[e]   #删除此连接对应的队列

注意:exceptional表示当这个连接出现问题了,那我服务端就不需要检测它了,那就要把链接的实例从inputs里面,outputs里面全都删除掉

4.3、alex的完整代码

Server端

#_*_coding:utf-8_*_
__author__ = 'Alex Li'import select
import socket
import sys
import queueserver = 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就是一个socketif 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]
select socket server

Client端

#_*_coding:utf-8_*_
__author__ = 'Alex Li'import socket
import sysmessages = [ b'This is the message. ',b'It will be sent ',b'in parts.',]
server_address = ('localhost', 10000)# Create a TCP/IP socket
socks = [ socket.socket(socket.AF_INET, socket.SOCK_STREAM),socket.socket(socket.AF_INET, socket.SOCK_STREAM),]# Connect the socket to the port where the server is listening
print('connecting to %s port %s' % server_address)
for s in socks:s.connect(server_address)for message in messages:# Send messages on both socketsfor s in socks:print('%s: sending "%s"' % (s.getsockname(), message) )s.send(message)# Read responses on both socketsfor s in socks:data = s.recv(1024)print( '%s: received "%s"' % (s.getsockname(), data) )if not data:print(sys.stderr, 'closing socket', s.getsockname() )
select socket client

 

转载于:https://www.cnblogs.com/zhangqigao/articles/7459379.html