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谁发生了变化。

 

 

posted @ 2018-08-16 14:29  Sky__liu  阅读(182)  评论(0)    收藏  举报