IO并发编程及二进制位运算

本文深入解析了计算机网络中的IO模型,包括阻塞IO、非阻塞IO、IO多路复用及异步IO的概念与实现。详细介绍了select、poll、epoll等方法在处理多个IO事件时的原理和应用,以及如何通过设置套接字属性提高IO处理效率。

IO 分类

IO分类:阻塞IO ,非阻塞IO,IO多路复用,异步IO等

阻塞IO

1.定义:在执行IO操作时如果执行条件不满足则阻塞。阻塞IO是IO的默认形态。

2.效率:阻塞IO是效率很低的一种IO。但是由于逻辑简单所以是默认IO行为。

3.阻塞情况:

  • 因为某种执行条件没有满足造成的函数阻塞
    e.g. accept input recv
  • 处理IO的时间较长产生的阻塞状态
    e.g. 网络传输,大文件读写
非阻塞IO

代码实现: day9/block_io

  1. 定义 :通过修改IO属性行为,使原本阻塞的IO变为非阻塞的状态。
  • 设置套接字为非阻塞IO

sockfd.setblocking(bool)
功能:设置套接字为非阻塞IO
参数:默认为True,表示套接字IO阻塞;设置为False则套接字IO变为非阻塞

  • 超时检测 :设置一个最长阻塞时间,超过该时间后则不再阻塞等待。

    sockfd.settimeout(sec)
    功能:设置套接字的超时时间
    参数:设置的时间

IO多路复用

  1. 定义

同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO事件。以此形成可以同时处理多个IO的行为,避免一个IO阻塞造成其他IO均无法执行,提高了IO执行效率。

  1. 具体方案

select方法 : windows linux unix
poll方法: linux unix
epoll方法: linux

select 方法

代码实现: day10/select_server.py

rs, ws, xs=select(rlist, wlist, xlist[, timeout])
功能: 监控IO事件,阻塞等待IO发生
参数:rlist  列表  读IO列表,添加等待发生的或者可读的IO事件
      wlist  列表  写IO列表,存放要可以主动处理的或者可写的IO事件
      xlist  列表 异常IO列表,存放出现异常要处理的IO事件
      timeout  超时时间

返回值: rs 列表  rlist中准备就绪的IO
        ws 列表  wlist中准备就绪的IO
	   xs 列表  xlist中准备就绪的IO

select 实现tcp服务

【1】将关注的IO放入对应的监控类别列表
【2】通过select函数进行监控
【3】遍历select返回值列表,确定就绪IO事件
【4】处理发生的IO事件

注意

wlist中如果存在IO事件,则select立即返回给ws
处理IO过程中不要出现死循环占有服务端的情况
IO多路复用消耗资源较少,效率较高


@@扩展: 位运算

定义 : 将整数转换为二进制,按二进制位进行运算

运算符号:

& 按位与
| 按位或
^ 按位异或
<< 左移
>> 右移

e.g.  14 --> 01110
      19 --> 10011

14 & 19 = 00010 = 200
14 | 19 = 11111 = 3111
14 ^ 19 = 11101 = 29 相同为0不同为1
14 << 2 = 111000 = 56 向左移动低位补0
14 >> 2 = 11 = 3  向右移动去掉低位

poll方法

代码实现: day10/poll_server.py

p = select.poll()
功能 : 创建poll对象
返回值: poll对象
p.register(fd,event)   
功能: 注册关注的IO事件
参数:fd  要关注的IO
      event  要关注的IO事件类型
  	     常用类型:POLLIN  读IO事件(rlist)
		      POLLOUT 写IO事件 (wlist)
		      POLLERR 异常IO  (xlist)
		      POLLHUP 断开连接 
		  e.g. p.register(sockfd,POLLIN|POLLERR)

p.unregister(fd)
功能:取消对IO的关注
参数:IO对象或者IO对象的fileno
events = p.poll()
功能: 阻塞等待监控的IO事件发生
返回值: 返回发生的IO
        events格式  [(fileno,event),()....]
        每个元组为一个就绪IO,元组第一项是该IO的fileno,第二项为该IO就绪的事件类型

poll_server 步骤

【1】 创建套接字
【2】 将套接字register
【3】 创建查找字典,并维护
【4】 循环监控IO发生
【5】 处理发生的IO
epoll方法

代码实现: day10/epoll_server.py

  1. 使用方法 : 基本与poll相同
    • 生成对象改为 epoll()
    • 将所有事件类型改为EPOLL类型
  2. epoll特点
    • epoll 效率比select poll要高
    • epoll 监控IO数量比select要多
    • epoll 的触发方式比poll要多 (EPOLLET边缘触发)
### 二进制在编程语言中的使用情况 某些编程语言在开发过程中需要直接处理或编写二进制数据,尤其是在与硬件交互、网络通信、嵌入式系统、图像处理等领域。这些语言通常允许开发者操作底层内存、位运算和原始字节流,以实现对数据的高效控制。 #### 汇编语言 汇编语言是一种低级语言,其指令与机器码一一对应,因此在本质上就是通过助记符来表示二进制代码。程序最终会被汇编器转换为对应的二进制指令,供计算机执行[^3]。例如: ```asm MOV AX, 0x1234 ADD AX, 0x0001 ``` 上述代码表示将十六进制数 `0x1234` 移动到寄存器 `AX` 中,然后加 `1`。这种语言非常适合操作系统内核、驱动程序等底层开发工作。 #### C/C++ C 和 C++ 是广泛用于系统级编程的语言,它们提供了对内存地址、指针和原始二进制数据的访问能力。例如,在网络传输中,常需将结构体序列化为二进制流进行发送: ```cpp #include <iostream> #include <fstream> struct Data { int id; float value; }; int main() { Data d = {1, 3.14f}; std::ofstream file("data.bin", std::ios::binary); file.write(reinterpret_cast<char*>(&d), sizeof(d)); file.close(); } ``` 这类语言支持按字节操作内存,适合开发高性能应用、嵌入式系统和游戏引擎等[^2]。 #### Python 尽管是高级语言,Python 同样具备强大的二进制处理能力。它可以通过内置模块如 `struct`、`bitarray` 或第三方库(如 NumPy、Pillow)处理图像、音频等二进制数据。例如,使用 `struct` 打包和解包二进制数据: ```python import struct # 将整数和浮点数打包成二进制格式 packed_data = struct.pack('i f', 1, 3.14) print(packed_data) # 解包二进制数据 unpacked_data = struct.unpack('i f', packed_data) print(unpacked_data) ``` 此外,Python 还可用于图像处理中的二进制操作,如使用 OpenCV 对图像进行裁剪和保存[^4]。 #### Rust Rust 是一种现代系统编程语言,强调安全性和性能。它支持底层内存操作,并能高效处理二进制数据,适用于加密算法、区块链开发、嵌入式设备等场景。例如,读取一个二进制文件的内容: ```rust use std::fs::File; use std::io::Read; fn main() -> std::io::Result<()> { let mut file = File::open("example.bin")?; let mut buffer = Vec::new(); file.read_to_end(&mut buffer)?; println!("Read {} bytes", buffer.len()); Ok(()) } ``` Rust 的所有权模型确保了内存安全,同时保持接近 C 的性能水平。 #### Go (Golang) Go 语言也支持高效的二进制处理,尤其在并发和网络服务方面表现出色。它提供标准库如 `encoding/binary` 来处理结构化的二进制数据: ```go package main import ( "bytes" "encoding/binary" "fmt" ) type Data struct { ID int32 Value float32 } func main() { var data Data = Data{ID: 1, Value: 3.14} buf := new(bytes.Buffer) err := binary.Write(buf, binary.LittleEndian, data) if err != nil { fmt.Println("binary.Write failed:", err) } fmt.Printf("%v\n", buf.Bytes()) } ``` 这使得 Go 成为构建后端服务、协议解析器的理想选择。 #### 其他语言 - **Java**:虽然 Java 抽象了底层细节,但依然可通过 `ByteBuffer` 和 NIO API 实现高效的二进制数据操作。 - **C#/.NET**:提供 `BinaryReader` 和 `BinaryWriter` 类,用于读写二进制文件,常见于游戏开发和 Windows 应用中。 - **MATLAB / Octave**:支持读写各种二进制文件(如 `.mat` 文件),并进行科学计算和信处理。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值