前言:

什么是IO?
  • 分为IO设备和IO接口两个部分
  • Linux系统,I/O操作可以有多种方式
  • 比如DIO(DirectI/O)
  • AIO(AsynchronousI/O异步I/O)
  • Memory-MappedI/O(内存映设I/O)等...
  • 不同的I/O方式有不同的实现方式和性能,在不同的应用中可以按情况选择不同的I/O方式。

补充昨天HTTP:


  1. from socket import *
  2. # 接收请求
  3. # 查看请求
  4. # 返回客户端段请求内容
  5.  
  6. def handleClient(connfd):
  7. request = connfd.recv(4096)
  8. # print("***********")
  9. # print(request)
  10. # print("************")
  11. # 按照行切割请求
  12. request_lines = request.splitlines()
  13. for line in request_lines:
  14. print(line.decode())
  15.  
  16. try:
  17. f = open('index.html')
  18. except IOError:
  19. response = "HTTP/1.1 303 Not Found\r\n"
  20. response += "\r\n" # 空行
  21. response += '''
  22. **************************
  23. Sorry, not found the page.
  24. **************************
  25. '''
  26. else:
  27. response = "HTTP/1.1 200 OK\r\n"
  28. response += '\r\n'
  29. response += f.read()
  30. finally:
  31. # 发送给浏览器
  32. connfd.send(response.encode())
  33.  
  34. # 创建套接字,调用handleClient完成功能
  35. def main():
  36. # 创建tcp套接字
  37. sockfd = socket()
  38. sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
  39. sockfd.bind(('0.0.0.0', 8000))
  40. sockfd.listen()
  41. while True:
  42. print("Listen the port 8000...")
  43. connfd, addr = sockfd.accept()
  44. # 处理浏览器发来的请求
  45. handleClient(connfd)
  46. connfd.close()
  47.  
  48. if __name__ == "__main__":
  49. main()
S.splitlines  
拆分文件字符串按行分隔
 
 
 
 
内存中存在数据交换的操作认为是IO操作(输入输出)
例如:
    内存与磁盘数据交换:文件读写、数据库更新
    内存和终端数据交换:input、print、sys.stdout、sys.stdin、  sys.stder
    内存和网络数据交换:网络连接、recv、send、recvfrom
 
IO秘集程型序:
     程序执行中有大量的IO操作,而比较少的CPU运算操作
     消耗CPU较少,IO运行时间长
cpu(计算)密集形程序:
     程序存在大量的CPU运算,IO操作相对较少
     CPU消耗大
 
IO分类:
    1.阻塞IO:
        程序运行中遇到IO条件没有达成
或传输情况较慢的情况下会出现阻塞状态
  阻塞IO是IO最简单的逻辑情形,也是默认状态
  阻塞IO是效率很低的IO状态
阻塞情况:
    1.因为IO条件没有达成
        IO阻塞函数(input、print、recv、recvfrom)
    2.处理IO耗时较长形参阻塞
        文件读写、网络数据发送过程
 
    2.非阻塞IO:
        在程序运行中遇到IO操作不让其产生阻塞
实现手段:
   改变IO事件的属性,使其变为非阻塞
   通常会和循环一起使用 进行条件的循环监控
 
    3.IO多路复用
        定义:
  通过一个监测,可以同时监控多个IO事件的行为
  当那个IO可以执行,让这个IO事件发生
  同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO事件
  此时形成多个IO时间都可以操作的现象,不必逐个等待执行
IO准备就绪:
  IO事件即将发生时的临界状态不可逆转
  在程序中存在的IO事件中选择要监测的事件
  创建监测,将监测的IO事件注册
  等待监测的IO事件发生判断是什么事件
  处理相应的IO
 
 
    事件驱动IO
    异步IO
    ...
 
s.setblocking(False)
   功能:
      将套接字设置为非阻塞状态
   参数:
      默认为阻塞, 设置为False为非阻塞状态
 
超时检测:
    原本阻塞的IO设置一个最长阻塞等待时间
    在规定时间内如果达到条件正常执行
    如果时间到仍未达到条件则结束阻塞
        s.settimeout(sec)
            功能:
                    设置套接字的超时时间
             参数:
                   时间(
 
 
select模块
from select import
select 支持:Windows、Linux、Unix  
poll   支持:Linux、Unix
epoll  支持:Linux、Unix
 
rs, ws, xs = select(rlist, wlist, xlist[, timeout])
   功能:
      监控IO事件 ,阻塞等待监控的IO事件发生
   参数:
       rlist   列表:
          表示存放我们需要等待处理的IO
       wlist   列表:
          表示存放我们想要主动处理的IO
       xlist   列表:
          表示存放出错希望去处理的IO
       timeout: 超时检测
   返回值:
      rs  列表:
          准备就绪的IO
      ws  列表:
          准备就绪的IO
      xs  列表
          准备就绪的IO
 
* 在处理IO时不要形成死循环会让一个客户端单独占有服务端
 
IO多路复兴形成一种可以同时处理多个IO的效果效率较高
 
 
位运算:
   按照二进制位进行位运算操作
   & 按为与   |  按位或   ^  按位异或
 
   << 左异    >>右移
 
   11  1011
   14  1110
 
   &   1010  有0得0
    |    1111  有1得1
   ^    0101  相同为0不同为1
  
   11 << 2  == 44   右侧补零(乘2乘2次)
   14 >> 2  == 3    挤掉右侧的数字(地板除2除2次)
使用:
    1.在低层硬件操作寄存器
    2.做标志位的过滤
 
 
 
poll方法实现IO多路复用:
   1.创建poll对象:
       p = select.poll
   2.注册关注的IO:
       p.register(s, POLLIN | PLLERR)
       不关注:
          p.unregister(s)
       事件类别:
          POLLIN  POLLOUT  POLLERR  POLLHUP   POLLPRI
            rlist           wlist          xlist          断开       紧急处理 
   3.监控IO:
       events = p.poll()
       功能:监控关注的IO事件
       返回值:
           返回发生IO事件
   events是一个列表[(fileno, evnet), (), ()....]
   每个就绪IO对应一个元组描述符就绪事件
           IO地图{s.fileno():s}
   4.处理IO事件
 
poll方法实现IO多路复用:
  1. from socket import *
  2. from select import *
  3.  
  4. s = socket()
  5. s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
  6. s.bind(('0.0.0.0',8888))
  7. s.listen(5)
  8.  
  9. #创建poll对象
  10. p = poll()
  11.  
  12. #创建地图
  13. fdmap = {s.fileno():s}
  14.  
  15. #添加关注
  16. p.register(s,POLLIN | POLLERR)
  17.  
  18. while True:
  19. #进行IO监控
  20. #[(fileno,evnet),...]
  21. events = p.poll()
  22. for fd,event in events:
  23. if fd == s.fileno():
  24. #从地图中找到fd对应的对象
  25. c,addr = fdmap[fd].accept()
  26. print("Connect from",addr)
  27. #注册新的IO 维护地图
  28. p.register(c,POLLIN)
  29. fdmap[c.fileno()] = c
  30. else:
  31. data = fdmap[fd].recv(1024)
  32. if not data:
  33. p.unregister(fd) #从关注移除
  34. fdmap[fd].close()
  35. del fdmap[fd] #从地图删除
  36. else:
  37. print(data.decode())
  38. fdmap[fd].send('收到了'.encode())
 
 
select IO多路复用服务器端:
 
  1. from socket import *
  2. from select import select
  3. # 创建套接字
  4. s = socket()
  5. # 设置端口重用
  6. s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
  7. # 绑定地址
  8. s.bind(('0.0.0.0', 8888))
  9. # 设置队列
  10. s.listen(5)
  11. # 注册监听套接字
  12. rlist = [s]
  13. wlist = []
  14. xlist = [s]
  15.  
  16. while True:
  17. print("等待IO发生")
  18. rs, ws, xs = select(rlist, wlist, xlist)
  19. # 循环遍历rs准备就绪列表
  20. for r in rs:
  21. # 如果有新的客户端链接请求
  22. if r is s:
  23. # 链接客户端并返回客户端套接字
  24. connfd, addr = r.accept() # r==s 原套接字
  25. print("Connect from", addr)
  26. # 将绑定客户端套接字加入监听列表
  27. rlist.append(connfd)
  28. # 表示客户端连接套接字准备就绪
  29. else:
  30. # 如果是客户端套接字发送数据 则接收
  31. data = r.recv(1024)
  32. if not data: # 如果客户端断开链接
  33. # 从关注列表移除connfd
  34. rlist.remove(r)
  35. r.close() # 关闭套接字
  36. else:
  37. print("Receive:", data.decode())
  38. # 讲客户端套接字放入wlist
  39. wlist.append(r)
  40. # wlist列表会直接返回
  41. # 循环遍历ws准备就绪列表
  42. for w in ws:
  43. # 消息回复
  44. w.send("这是一条回复消息".encode())
  45. # 删除并取消监听已处理消息
  46. wlist.remove(w)
  47. # xs列表:待处理异常
  48. for x in xs:
  49. if x is s:
  50. s.close()

 
 
 
 
sys.stdin
 
 
 
 
 
客户端:
 

  1. from socket import *
  2.  
  3. #  创建套接字
  4. sockfd = socket()
  5.  
  6. #  发起连接
  7. sockfd.connect(('127.0.0.1', 8888))
  8.  
  9. while True:
  10. #  消息收发
  11. msg = input("Msg>>")
  12. if not msg:
  13. break
  14. sockfd.sendall(msg.encode())
  15. data = sockfd.recv(1024)
  16. print(data.decode())
  17.  
  18. sockfd.close()
应用 :
select服务端,同时关注客户端连接
客户端发送和终端输入。将客户端发送和终端输入的内容全都写入到一个文件中
 

  1. # myserver.py
  2. # 应用 :
  3. # select服务端,同时关注客户端连接
  4. # 客户端发送和终端输入。将客户端发送和终端输入的内容全都写入到一个文件中
  5.  
  6. from socket import *
  7. from select import *
  8. from sys import stdin
  9.  
  10. sock = socket()
  11. sock.getsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
  12. sock.bind(("127.0.0.1", 6666))
  13. sock.listen(5)
  14. rlist = [sock, stdin]
  15. wlist = []
  16. xlist = []
  17. file = open("selectdemo.txt", "w+b")
  18. while True:
  19. rs, ws, xs, = select(rlist, wlist, xlist)
  20. for r in rs:
  21. if r == sock:
  22. connfd, addr = r.accept()
  23. print("已连接......")
  24. rlist.append(connfd)
  25. elif r == stdin:
  26. data = stdin.readline()
  27. file.write(data.encode())
  28. file.flush()
  29. else:
  30. data = r.recv(4096)
  31. if not data:
  32. rlist.remove(r)
  33. r.close()
  34. else:
  35. file.write(data + "\n".encode())
  36. file.flush()
  37. print("已经接收内容并写如select>>>.txt文件内\n 内容:", data.decode())
  38. r.send("接收成功!".encode())
  39. file.close()

  1. from socket import *
  2.  
  3. #  创建套接字
  4. sockfd = socket()
  5.  
  6. #  发起连接
  7. sockfd.connect(('127.0.0.1', 6666))
  8.  
  9. while True:
  10. #  消息收发
  11. msg = input("Msg>>")
  12. if not msg:
  13. break
  14. sockfd.sendall(msg.encode())
  15. data = sockfd.recv(1024)
  16. print(data.decode())
  17.  
  18. sockfd.close()
 
 
 

Python网络编程(http协议,IO多路复用、select内核监听)的更多相关文章

  1. 网络编程socket 结合IO多路复用select; epool机制分别实现单线程并发TCP服务器

    select版-TCP服务器 1. select 原理 在多路复用的模型中,比较常用的有select模型和epoll模型.这两个都是系统接口,由操作系统提供.当然,Python的select模块进行了 ...

  2. python 网络编程 -- Tcp协议

    Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可. 客户端 大多数连接都是可靠 ...

  3. python网络编程-TCP协议中的三次握手和四次挥手(图解)

    建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资 ...

  4. Python网络编程:IO多路复用

    io多路复用:可以监听多个文件描述符(socket对象)(文件句柄),一旦文件句柄出现变化,即可感知. sk1 = socket.socket() sk1.bind(('127.0.0.1',8001 ...

  5. python网络编程——SocketServer/Twisted/paramiko模块

    在之前博客C/S架构的网络编程中,IO多路复用是将多个IO操作复用到1个服务端进程中进行处理,即无论有多少个客户端进行连接请求,服务端始终只有1个进程对客户端进行响应,这样的好处是节省了系统开销(se ...

  6. 第五十五节,IO多路复用select模块加socket模块,伪多线并发

    IO多路复用select模块加socket模块,伪多线并发,并不是真正的多线程并发,实际通过循环等待还是一个一个处理的 IO多路复用,lo就是文件或数据的输入输出,IO多路复用就是可以多用户操作 IO ...

  7. python网络编程——IO多路复用之select

    1 IO多路复用的概念 原生socket客户端在与服务端建立连接时,即服务端调用accept方法时是阻塞的,同时服务端和客户端在收发数据(调用recv.send.sendall)时也是阻塞的.原生so ...

  8. python 网络编程 IO多路复用之epoll

    python网络编程——IO多路复用之epoll 1.内核EPOLL模型讲解     此部分参考http://blog.csdn.net/mango_song/article/details/4264 ...

  9. Python实战之IO多路复用select的详细简单练习

    IO多路复用 I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. select   它通过一个select()系统调用来 ...

随机推荐

  1. A. Round House_数学问题

    A. Round House time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  2. Poj(1125),Floyd,

    题目链接:http://poj.org/problem?id=1125 多源点最短路中的,最长路的,最短路. 看到这里就懵逼了,解释一下,找到一个源点,使得路最短,(遍历源点),路最短怎么求呢? 就是 ...

  3. sql server 基础

    1 .左连接 select a.* ,b.* from student as aleft join hobby as bon a.hobbyid=b.hobbyid 2. 右 连接 select a. ...

  4. 如何提高mysql的安全性?

    1.如果 MySQL 客户端和服务器端的连接需要跨越并通过不可信任的网络,那么需要使用 ssh 隧道来加密该连接的通信.2.使用 set password 语句来修改用户的密码,先“mysql -u ...

  5. AngularJS 重复HTML元素

    data-ng-repeat指令会重复一个HTML元素 <!DOCTYPE html><html><head><meta http-equiv="C ...

  6. 一篇SSM框架整合友好的文章(三)

    ###一.SpringMVC理论 它始终是围绕 handler. 数据模型 model. 页面view进行开发的. 运行流程图: 通过mvc配置文件,配置"中央处理器"dispat ...

  7. 2017年10月26日 git上传文件失败的文件

    最近几天因为项目要用git,于是学习了一下git.今天上传项目到码云的时候,却发现总有一些文件夹上传不上去,git 也显示everything is update.找了一圈办法,都没有用,最后突然发现 ...

  8. Redis高可用

    redis高可用只要在于三个方面 主从复制 哨兵机制 集群机制 主从复制 主从复制作用: 1.数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式.2.故障恢复:当主节点出现问题时,可 ...

  9. 基于Xtrabackup恢复单个innodb表

      Preface       We all know that Xtrabackup is a backup tool of percona for innodb or Xtradb.It's us ...

  10. kubernetes基础架构及原理

    kubernetes简称“k8s” 其中“8”代表的是“k”和“s”中间的8个字母. k8s是Google公司开发的Borg项目中独立出来的容器编排工具,然后将其捐献给CNCF这个组织,然后发扬光大. ...