• 02select监听服务端


    # can_read, can_write, _ = select.select(inputs, outputs, None, None)
    #
    # 第一个参数是我们需要监听可读的套接字, 第二个参数是我们需要监听可写的套接字, 第三个参数使我们需要监听异常的套接字, 第四个则是时间限制设置.
    #
    # 如果监听的套接字满足了可读可写条件, 那么所返回的can,read 或是 can_write就会有值了, 然后我们就可以利用这些返回值进行随后的操作了。相比较unix 的select模型, 其select函数的返回值是一个整型, 用以判断是否执行成功.
    #
    # 第一个参数就是服务器端的socket, 第二个是我们在运行过程中存储的客户端的socket, 第三个存储错误信息。
    # 重点是在返回值, 第一个返回的是可读的list, 第二个存储的是可写的list, 第三个存储的是错误信息的
    # list。
    import select, socket, queue
    from time import sleep

    # 创造一个 TCP/IP连接
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置socket为异步模式。
    server.setblocking(False)

    # 绑定IP地址和端口
    # 创建一个IP,端口,本地IP
    server_address = ('localhost', 8090)
    print('starting up on %s port %s' % server_address)
    # 绑定IP和端口
    server.bind(server_address)

    # 设置服务端监听数量
    server.listen(3)
    inputs = [server]
    # 处理要发送的数据
    outputs = []

    # 输出的消息队列
    message_queues = {}

    while inputs:
    # 等待至少一个连接开始调用线程
    print("waiting for the next event")
    # 开始select监听,对input_list中的服务器端的server开始进行监听
    # 一旦调用socket的send,recv函数,将会再次调用此模块
    # 这里监控三个参数,第一个返回的是可读的list, 第二个存储的是可写的list, 第三个存储的是错误信息的
    readable, writable, exceptional = select.select(inputs, outputs, inputs)

    # 处理输入
    # 循环判断是否有客户端连接进来,当有客户端连接进来的时候select将进行触发
    for s in readable:
    # 判断当前触发的是不是服务端对象,当触发的是服务端对象, 说明有新的客户端连接进来了
    if s is server:
    # 和客户端建立连接
    connection, client_address = s.accept()
    # 打印客户端的链接
    print('connection from', client_address)
    # 设置socket为异步模式。
    connection.setblocking(0)
    # 将客户端对象也加入到监听列表中,当客户端发送消息的时候select也会触发。
    inputs.append(connection)

    # 为连接的客户端单独建立一个消息队列,用来保存客户端发送的消息
    message_queues[connection] = queue.Queue()
    else:
    # 有老用户发送消息,处理接收
    # 由于客户端连接进来的时候服务端接收客户端的请求,将客户端也加入到了监听列表。
    # 客户端发送的消息将触发。
    # 判断触发对象是否为客户端
    # 接收客户端的信息
    data = s.recv(1024)
    # 客户端没有断开
    if data != '':
    # 一个可用的客户端发送了数据
    print('received "%s" from %s' % (data, s.getpeername()))
    # 将接受到的消息放到对应的客户端的消息队列中
    message_queues[s].put(data)
    # 将需要进行回复操作的socket放到output列表中,让select监听
    # 这里我们如果收到消息将服务端添加进入输出列表。
    # 然后select就会监听到,
    if s not in outputs:
    outputs.append(s)
    else:
    # 客户端被监听到有变化,不是有客户端传过来的消息,就是客户端断开了。
    # 客户端断开了连接,将客户端的监听从input列表中移除
    print('closing', client_address)
    if s in outputs:
    outputs.remove(s)
    inputs.remove(s)
    s.close()

    # 移除对应的socket客户端对象的消息队列
    del message_queues[s]

    # 处理输出。
    # 如果现在没有客户端的请求,也没有客户端发送消息时,开始对发送的消息列表进行处理。
    # 判断是否需要发送消息。
    # 存储哪个客户端发送了消息。
    for s in writable:
    try:
    # 如果消息队列中有消息,就从消息队列中获取要发送的消息。
    message_queue = message_queues.get(s)
    sent_data = ''
    if message_queues 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)

























  • 相关阅读:
    js基础练习题(2)
    js基础练习题(1)
    DOM-BOM-EVENT(7)
    DOM-BOM-EVENT(6)
    DOM-BOM-EVENT(5)
    DOM-BOM-EVENT(4)
    DOM-BOM-EVENT(3)
    Spark学习笔记--Spark在Windows下的环境搭建(转)
    idea下关联spark源码环境(转)
    Spark 性能相关参数配置详解-任务调度篇
  • 原文地址:https://www.cnblogs.com/cong12586/p/14071328.html
Copyright © 2020-2023  润新知