IO

IO   input   output
在内存中存在数据交换的操作都可以认为是IO操作
和终端交互 : input print
和磁盘交互 : read write
和网络交互 : recv send
  • IO密集型程序:在程序执行过程中存在大量IO操作,而cpu运算操作较少,消耗cpu较少,运行效率较低

  • 计算密集型程序(CUP密集型程序):在程序执行中CPU运算较多,IO操作相对较少,消耗CPU大,运行速度快

  • IO分类

    • 阻塞IO
    • 非阻塞IO
    • IO多路复用

阻塞IO

  • 阻塞IO是IO的默认形态,是效率较低的一种IO情形。
  • 阻塞情况
    • 因为某种条件没有达成造成的阻塞

      • e.g. accept input recv
    • 处理IO数据传输时间较长形成的阻塞
      • e.g. 网络传输过程,文件读写过程

非阻塞IO

  • 通过修改IO事件的属性,使其变为非阻塞状态(让一些条件阻塞函数不再阻塞)

    • 非阻塞IO往往和循环判断一起使用

      s.setblocking(False)

      将套接字设置为非阻塞状态
# 设置非阻塞
from socket import *
from time import sleep,ctime s = socket()
s.bind(('127.0.0.1',9999))
s.listen(3) #将套接字设置为非阻塞
s.setblocking(False) while True:
print("Waiting for connect...")
try:
c,addr = s.accept()
except BlockingIOError:
sleep(2)
print(ctime())
continue
else:
print("Connected from",addr)
while True:
data = c.recv(1024).decode()
if not data:
break
print(data)
c.send(ctime().encode())
c.close()
s.close()
  • 超时检测

    • 将原本阻塞的函数设置一个最长阻塞时间,如果时间内条件达成则正常运行,如果仍然阻塞则视为超时,继续向下运行或产生异常

        s.settimeout(sec)
      设置套接字的超时时间
# 设置超时时间
from socket import *
from time import sleep,ctime s = socket()
s.bind(('127.0.0.1',8888))
s.listen(3) #将套接字设置超时时间
s.settimeout(5) while True:
print("Waiting for connect...")
try:
c,addr = s.accept()
except timeout:
print(ctime())
continue
else:
print("Connect from",addr)
while True:
data = c.recv(1024).decode()
if not data:
break
print(data)
c.send(ctime().encode())
c.close()
s.close()

IO多路复用

  • 定义:同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO事件,以此形成可用同时操作多个IO的并发行为,避免一个IO阻塞,造成所有IO都无法执行。

  • IO准备就绪:是一种IO必然要发生的临界状态

  • IO多路复用的编程实现

    1. 将IO设置为关注IO
    2. 将关注IO提交给内核监测
    3. 处理内核给我们反馈的准备就绪的IO
  • 具体方案:

    select --> linux unix windows

    poll --> linux unix

    epoll --> linux unix

select

import select

rs,ws,xs = select(rlist, wlist, xlist[, timeout])

  • 功能:监控IO事件,阻塞等待IO事件发生

  • 参数:

    • rlist..列表..存放我们监控等待处理的IO事件
    • wlist..列表..存放我们要主动操作的IO事件
    • xlist..列表..我们要关注出错处理的IO事件
    • timeout..超时时间
  • 返回值:

    • rs..列表..rlist中准备就绪的IO
    • ws..列表..wlist中准备就绪的IO
    • xs..列表..xlist中准备就绪的IO
  • 注意:

    1. wlist中如果有IO事件则select立即回返回为ws
    2. 在处理IO过程中不要处理一个客户端长期占有服务端使服务端无法运行到select的情况
    3. IO多路复用占用计算机资源少,io效率高
from select import select
from socket import * #创建套接字作为我们关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',9999))
s.listen(5) rlist = [s]
wlist = []
xlist = [s] while True:
#提交监测我们关注的IO等待IO发生
rs,ws,xs = select(rlist,wlist,xlist)
for r in rs:
if r is s:
c,addr = r.accept()
print("Connect from",addr)
rlist.append(c) #添加到关注列表
else:
data = r.recv(1024)
if not data:
rlist.remove(r)
r.close()
else:
print(data.decode())
# r.send(b'Receive your message')
#将客户端套接字放入wlist列表
wlist.append(r) for w in ws:
w.send(b'Receive your message')
wlist.remove(w) for x in xs:
if x is s:
s.close()

位运算

  • 整数按照二进制位进行运算

    • &:按位与

    • |:按位或

    • ^:按位异或

    • <<:左移

    • >>:右移

      11 1011

      14 1110

      14 & 11 : 1010 一0则0

      14 | 11 : 1111 一1则1

      14 ^ 11 : 0101 相同为0不同为1

      11 << 2 : 101100 右侧补零

      14 >> 2 : 11

poll

  1. 创建poll对象

    p = select.poll()

  2. 添加注册事件

    p.register(s, POLLIN | POLLERR)

     POLLIN   POLLOUT  POLLERR  POLLHUP  POLLNVAL
    rlist wlist xlist 断开 无效数据 p.unregister(s) 从关注事件中移除
  3. 阻塞等待IO发生

    events = p.poll()

    • 功能:阻塞等待IO发生

    • 返回值:events 是一个列表,列表中给每一个元素都是一个元组,代表一个发生的IO事件

        [(fileno, event),(),()....]
      就绪IO的文件描述符, 具体就绪事件
    • 需要通过文件描述符(fileno)找到对应的IO对象

      {s.fileno() : s}

  4. 处理具体的IO

from socket import *
from select import * #创建套接字作为我们关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',9999))
s.listen(5) #创建poll对象
p = poll() #fileno ---> IO对象的字典
fdmap = {s.fileno():s} #注册关注的IO
p.register(s,POLLIN | POLLERR) while True:
#进行IO监控
events = p.poll()
for fd,event in events:
if fd == s.fileno():
c,addr = fdmap[fd].accept()
print("Connect from",addr)
#添加新的关注事件
p.register(c,POLLIN | POLLHUP)
fdmap[c.fileno()] = c
elif event & POLLIN: # 若是真,POLLIN就绪
data = fdmap[fd].recv(1024)
if not data:
#客户端退出,从关注事件移除
p.unregister(fd)
fdmap[fd].close()
del fdmap[fd]
else:
print(data.decode())
fdmap[fd].send(b'Receive')

epoll

  • 使用方法:基本与poll方法相同

    • 将生产对象 poll() 改为epoll()
    • 将所有poll对象事件改为epoll对象事件
  • 区别 :

    • epoll 的效率要比 poll和select 高
    • epoll 的事件触发方式更多
from socket import *
from select import * #创建套接字作为我们关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',9999))
s.listen(5) #创建epoll对象
p = epoll() #fileno ---> IO对象的字典
fdmap = {s.fileno():s} #注册关注的IO
p.register(s,EPOLLIN | EPOLLERR) while True:
#进行IO监控
events = p.poll()
for fd,event in events:
if fd == s.fileno():
c,addr = fdmap[fd].accept()
print("Connect from",addr)
#添加新的关注事件
p.register(c,EPOLLIN | EPOLLHUP)
fdmap[c.fileno()] = c
elif event & EPOLLIN:
data = fdmap[fd].recv(1024)
if not data:
#客户端退出,从关注事件移除
p.unregister(fd)
fdmap[fd].close()
del fdmap[fd]
else:
print(data.decode())
fdmap[fd].send(b'Receive')

PythonNET网络编程3的更多相关文章

  1. PythonNET网络编程1

    # PythonNET 网络编程 ISO(国际标准化组织) 制定了 OSI(Open System Interconnectio),意为开放式系统互联.国际标准化组织(ISO)制定了OSI模型,该模型 ...

  2. PythonNET网络编程4

    本地套接字 Linux 文件 b(块设备文件) c(字符设备文件) d(目录) -(普通文件) l(链接) s(套接字) p(管道) 作用:用于本地不同的程序间进行通信 创建流程 创建本地套接字 so ...

  3. PythonNET网络编程2

    UDP应用:广播 广播:一点发送,多点接收 广播地址:一个网段内有一个指定的广播地址,是该网段的最大地址 192.168.2.255 广播风暴:一个网络中有大量的广播就会产生广播风暴占用大量带宽,影响 ...

  4. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

  5. python select网络编程详细介绍

    刚看了反应堆模式的原理,特意复习了socket编程,本文主要介绍python的基本socket使用和select使用,主要用于了解socket通信过程 一.socket模块 socket - Low- ...

  6. Linux Socket 网络编程

    Linux下的网络编程指的是socket套接字编程,入门比较简单.在学校里学过一些皮毛,平时就是自学玩,没有见识过真正的socket编程大程序,比较遗憾.总感觉每次看的时候都有收获,但是每次看完了之后 ...

  7. 猫哥网络编程系列:详解 BAT 面试题

    从产品上线前的接口开发和调试,到上线后的 bug 定位.性能优化,网络编程知识贯穿着一个互联网产品的整个生命周期.不论你是前后端的开发岗位,还是 SQA.运维等其他技术岗位,掌握网络编程知识均是岗位的 ...

  8. 浅谈C#网络编程(一)

    阅读目录: 基础 Socket编程 多线程并发 阻塞式同步IO 基础 在现今软件开发中,网络编程是非常重要的一部分,本文简要介绍下网络编程的概念和实践. Socket是一种网络编程接口,它是对传输层T ...

  9. C++11网络编程

    Handy是一个简洁优雅的C++11网络库,适用于linux与Mac平台.十行代码即可完成一个完整的网络服务器. 下面是echo服务器的代码: #include <handy/handy.h&g ...

随机推荐

  1. K-序列(埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛)

    题目描述 给一个数组 a,长度为 n,若某个子序列中的和为 K 的倍数,那么这个序列被称为“K 序列”.现在要你 对数组 a 求出最长的子序列的长度,满足这个序列是 K 序列.  输入描述: 第一行为 ...

  2. 请允许我成为你的夏季——shiro、jdbcInsertall

    这两天总是觉得自己被关进了一个大笼子,日子拮据.生活不就是这样吗,一边觉得自己很差劲,一边又想成为一个更好的自己.可那又有什么办法呢,万物皆有裂痕,但那又怎样,那是光照进来的地方啊. 开始学习shir ...

  3. @Mapper 和 @MapperScan 区别

    1.@Mapper : 为了使接口被其他类引用,需要使用@Mapper注解,这种方式要求每一个mapper类都需要添加此注解,麻烦. package com.example.demo.dao; imp ...

  4. cogs 1500. 误差曲线

    1500. 误差曲线 ★★   输入文件:errorcurves.in   输出文件:errorcurves.out   评测插件时间限制:1 s   内存限制:256 MB [题目描述] Josep ...

  5. 自写的开发框架,胜于官方的clientAPP的实战开发。(已开源)

    已开源,欢迎大家fork 小弟github地址为https://github.com/10045125/vanda 好久没写博客了,这段时间主要是要做的事情太多.如今接触android有段时间了.非常 ...

  6. struts2学习笔记(7)---数据验证之validateXxx()方法

    validateXxx()方法 上一篇文章写了使用Action的validate()方法,validate()仅仅能对action的所有方法进行验证.而要实现对action中特定的方法进行验证,就须要 ...

  7. QQ互联账号登录

    本文说明的是依据某应用通过网页的qq信息来登录的过程.用途是利用QQ账号就能高速自己主动注冊并可以登录客户应用. 从webserver与腾讯server通信获取开房平台用户OpenID,再在应用ser ...

  8. Codeforces 429D Tricky Function 近期点对

    题目链接:点击打开链接 暴力出奇迹. 正解应该是近期点对.以i点为x轴,sum[i](前缀和)为y轴,求随意两点间的距离. 先来个科学的暴力代码: #include<stdio.h> #i ...

  9. 搭建个人博客 方式2 使用jekyll

    孙广东  2016.3.12 环境安装:1.通过 RailsInstaller  来安装 Ruby https://www.ruby-lang.org/zh_cn/documentation/inst ...

  10. 带你彻彻底底弄懂Scroller

    Scroller的使用 这是一个滑动帮助类.并不能够使View真正的滑动,而是依据时间的流逝.获取插值器中的数据.传递给我们.让我们去配合scrollTo/scrollBy去让view产生缓慢滑动,产 ...