zoukankan      html  css  js  c++  java
  • PythonStudy——多路复用IO select实现

    # 服务端代码
    import socket
    import select
    
    
    server = socket.socket()
    server.bind(("127.0.0.1", 1688))
    server.listen(5)
    
    # server.setblocking(False)
    
    rlist = [server, ]  # 将需要检测(是否可读==recv)的socket对象放到该列表中
    # accept也是一个读数据操作,默认也会阻塞  也需要让select来检测
    
    # 注意 select最多能检测1024个socket 超出直接报错    这是select自身设计的问题    最终的解决方案epoll
    
    wlist = []  # 将需要检测(是否可写==send)的socket对象放到该列表中
    # 只要缓冲区不满都可以写
    
    msgs = [("socket", "msg")]  # 存储需要发送的数据  等待select 检测后 在进行发送
    
    print("start")
    while True:
        readable_list, writeable_list, _ = select.select(rlist, wlist, [])  # 会阻塞等到 有一个或多个socket 可以被处理
        print("%s个socket可读" % len(readable_list), "%s个socket可写" % len(writeable_list))
    
        """
        readable_list 中存储的是已经可以读取数据的socket对象   可能是服务器 可能是客户端
        """
        # 处理可读列表
        for soc in readable_list:
            if soc == server:
                # 服务器的处理
                client, addr = server.accept()
                # 将新连接的socket对象 加入到待检测列表中
                rlist.append(client)
            else:
                try:
                    # 客户端的处理
                    data = soc.recv(2048)
                    if not data:
                        soc.close()
                        rlist.remove(soc)  # 如果对方下线  关闭socket 并且从待检测列表中删除
                        continue
                    # 不能直接发  因为此时缓冲区可能已经满了    导致send阻塞住, 所以要发送数据前一个先这个socket交给select来检查
                    # soc.send(data.upper())
                    if soc not in wlist:
                        wlist.append(soc)
                    # 将要发送的数据先存起来
                    msgs.append((soc, data))
                except ConnectionResetError:
                    soc.close()
                    # 对方下线后 应该从待检测列表中删除 socket
                    rlist.remove(soc)
                    wlist.remove(soc)
        # 处理可写列表
        for soc in writeable_list:
            # 由于一个客户端可能有多个数据要发送 所以遍历所有客户端
            for i in msgs[:]:
                if i[0] == soc:
                    soc.send(i[1])
                    # 发送成功  将这个数据从列表中删除
                    msgs.remove(i)
            # 数据已经都发给客户端   这个socket还需不需要检测是否可写,必须要删除
            wlist.remove(soc)  # 否则 只要缓冲区不满 一直处于可写 导致死循环
    # 客户端代码
    import socket
    
    client = socket.socket()
    client.connect(("127.0.0.1",1688))
  • 相关阅读:
    复杂json对应的实体类定义
    Hbase 根据rowkey批量读写
    Spark 分组聚合转Map 的方式
    idea本地连接访问hadoop集群的方法
    新版supperset连接druid数据源设置
    使用jdbc java 连接 sqlserver 2008数据库 需要注意的事项
    关于CrystalQuartz设置Cron匹配的时区问题~
    VS2010连接远程TFS2012项目问题
    关于ASP.NET SignalR的Group使用
    关于CodeFrist下EntityFramework5.0及其最新版本中枚举的使用
  • 原文地址:https://www.cnblogs.com/tingguoguoyo/p/10999804.html
Copyright © 2011-2022 走看看