python 并发服务器2

  • 6.poll
    • poll解决了套接字有上限的问题,效率和select一样,都是轮询方式。
  • 7.单进程tcp服务器 epoll版 (windows不支持)
    • epoll-->解决支持上限问题-->采用的是事件通知(效率高)
    • 代码
    • import select
    • from socket import *
    • print(dir(select))
    • server_socket=socket(AF_INET,SOCK_STREAM)
    • server_socket.bind(("",9999))
    • server_socket.listen(5)
    • epol=epoll()  # 创建epoll对象
    • epol.register(server_socket.fileno(),EPOLLIN|EPOLLET) # 注册事件
    • socket_list={}  # 装socket的列表
    • socket_addr={}  #装socket的地址
    • while True:
      • print("-------1111111-------")
      • epoll_list=epol.poll()  # [(fd,事件),(),(),()]
      • print("--------22222------")
      • for fd,event in epoll_list:
        • # 有新的连接
        • if fd==server_socket.fileno():
          • new_socket,new_addr=server_socket.accept()
          • #\往子典中添加数据
          • socket_list[new_socket.fileno()]=new_socket
          • socket_addr[new_socket.fileno()]=new_addr
          • # 注册事件
          • epol.register(new_socket.fileno(),EPOLLIN|EPOLLET)
        • elif event==EPOLLIN:
          • print("哈哈哈!收到数据了")
          • new_socket=socket_list[fd]
          • new_addr=socket_addr[fd]
          • # 读取数据
          • content=new_socket.recv(1024)
          • if len(content)>0:
            • print("收到数据是:",content.decode("utf-8"))
          • else:
            • epol.unregister(fd)  # 取消注册
            • new_socket.close()
            • print(new_addr,"下线了....")
    • 优点:
      • 1.没有最大并发连接的限制,能打开的FD(指的是文件描述符,通俗的理解就是套接字对应的数字编号)的上限远大于1024。
      • 2.epoll采用的事件通知机制,效率高,不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数;即epoll最大的优点就在于它只管你“活跃”的连接,
        • 而跟连接总数无关,因此在实际的网络环境中,epoll的效率就会远远高于select和poll。
  • 8.拓展-文件描述符
    • 1.python中fileno() 方法返回一个整型的文件描述符(file descriptor)  打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。
    • 2.它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,会给这个文件指定一个文件描述符
    • 3.习惯上,标准输入sys.stdin.fileno() 的文件描述符为 0 标准输出sys.stdout.fileno() 的文件描述符为 1  标准错误sys.stderr.fileno() 的文件描述符为 2
  • 9.协程
    • 1.进程,线程,协程(微线程)
    • 2.协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时。协程,则只使用一个线程,分解一个线程成为多个“微线程”,在一个线程中规定某个代码块的执行顺序。
    • 3.协程的应用场景:当程序中存在大量不需要CPU的操作时(IO),线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,
    • 4.协程-greenlet-手动切换
      • from greenlet import greenlet
      • g1=greenlet(协程任务函数名)  创建greennlet对象
      • g1.switch()  执行协程并切换
      • 使用多个greenlet对象实现多个协程之间的手动切换
    • 5.协程-gevent-自动切换
      • import gevent
      • g1=gevent.spawn(协程任务函数名,参数)  创建gevent 对象 并执行
      • g1.join() 让线程等待协程执行完毕,否则没机会执行
      • 正常开发中,遇到好事操作自动切换协程,(可以在协程中使用gevent.sleep(1)手动搭建耗时操作)
      • 也可以使用 gevent.joinall([协程对象1,协程对像2,协程对象n])
      • gevent.getcurrent() 返回协程对象
      • 并发下载器
        • from gevent import monkey  
        • monkey.patch_all()#猴子补丁,将标准库中涉及的IO操作换成gevent的
        • import gevent
        • import urllib.request
        • #下载地址
        • def my_download(url):
          • print("GET url==%s" % url)
          • result = urllib.request.urlopen(url)
          • data = result.read()
          • print("url==%s,data is len=%s" % (url,len(data)))
        • gevent.joinall([
          • gevent.spawn(my_download,"https://www.baidu.com"),
          • gevent.spawn(my_download,"http://www.atguigu.com"),
          • gevent.spawn(my_download,"https://github.com"),
          • gevent.spawn(my_download,"http://www.atguigu.com/images/logo.gif"),
        • ])
    • 10.单进程tcp服务器 gevent 版
      • from gevent import monkey,socket,spawn
      • monkey.path_all()    #把标准库中的socket等给替换掉.
      • def server(new_socket):
        • while True:
          • content=new_socket.recv(1024)
          • if len(content)==0:
            • print("客户端下线")
            • break
          • print("收到消息:%s"%content.decode("utf-8"))
      • if __name__=="__main__":
        • server_socket=socket.socket()  #使用gevent中的socket
        • server_socket.bind(("",9999))
        • server.listen(5)
        • while True:
          • new_socket,new_addr=server.socket.accept()
          • spawn(server,new_socket)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值