python基础—IO模型

目录​​​​​​​

1. IO模型

阻塞实例(单进程):

 多线程服务器实例:

1. IO模型

IO模型:
    1)IO通信模型--Linux兼容绝大多数模型+windowsIO模型
        IO= input output  输入输出
        四个基本概念:
            同步--有序:多个程序之间协调一致,依次进行。
            异步--无序:多个程序之间执行顺序不确定,可以交替执行。
            阻塞:一个程序在等待某个操作完成,程序自身处于等待状态、停止运行,直到这个操作完成,程序才开始运行
            非阻塞:一个程序在等待某个操作完成,程序自身不会处于停止状态,而继续执行其他的任务
        
    五种IO模型:
            阻塞模型:单进程、编程思想简单
            非阻塞模型:多进程或线程、代码执行效率较高
            IO多路复用模型:单进程,通过文件描述符(操作文件返回的句柄)监听外部事件select、poll、epoll
                with open('demo.txt','r') as f:
                    
            信号驱动模型: 单进程,使用信号来监听
            异步IO模型: 提交任务和获取结果不在同一时间
        
    协程:
        1. gevent
        2. greenlet
    
    Scrapy:
        
"""

阻塞实例(单进程):

tcp通讯模型----爬虫http应用层使用传输层的tcp协议基础 

服务器代码:

from socket import socket, AF_INET, SOCK_STREAM

ip_port = ('', 1234) #端口,''部分通常也可以写本机ip
tcp_server_sock = socket(AF_INET,SOCK_STREAM) #创建一个TCP的socket
tcp_server_sock.setblocking(False)  #设置阻塞模式,False参数表示非阻塞
tcp_server_sock.bind(ip_port) #绑定端口
tcp_server_sock.listen() #监听

#阻塞
while True:
    print('等待连接...')
    try:
        try:
            tcp_extension_sock, addr = tcp_server_sock.accept() #接受信息的地址
        except BlockingIOError:
            continue
    except KeyboardInterrupt:
        break
    print('连接到地址是:{}'.format(addr))
    while True:
        try:
            data = tcp_extension_sock.recv(1024)
        except BlockingIOError:
            continue
        if not data:
            break
        print('收到数据:{}'.format(data.decode()))
        tcp_extension_sock.send('{} {}'.format(
            '[blocking-server]',data.decode()
        ).encode()) #发送信息
    tcp_extension_sock.close()
tcp_server_sock.close()

 客户端代码:

from socket import socket,AF_INET, SOCK_STREAM

tcp_client_sock = socket(AF_INET,SOCK_STREAM)
tcp_client_sock.connect(('127.0.0.1',1234))
while True:
    data = input('输入内容:')
    if not data:
        break
    tcp_client_sock.send(data.encode())
    data = tcp_client_sock.recv(1024)
    if not data:
        break
    print(data.decode())
tcp_client_sock.close()

TCP: 绑定系统资源-ip+端口号才能找到一个应用
    创建套接字:socket(AF_INET, SOCK_STREAM)
    绑定端口和ip: IP=“”,接收任何ip连接, IP = 'locahoast'是连接本地
                  端口号范围:1-65535
                    通常申请的端口号都在1000以上,最好端口号定在8000以外在写服务器代码时
                    原因是系统自带服务已经占用了一部分端口号比如:21,22,23等等
                    
    socket通讯模型发送数据的格式是字节码
        str = "name"
        bytes_str = str.encode() #把上面的“name”编成字节码(编码)
        recv = bytes_str.decode() #解码
    
1. 单进程TCP,通讯模型效率低
2. 多线程TCP,通讯模型效率提升,但是系统资源消耗成倍增加
3. IO多路复用,单进程多任务  
    tcp默认采用阻塞式通讯
        方法1:accept方法
        方法2:recv方法   
    一个进程监视多个文件描述符,其中一个或者多个文件描述符准备好,系统内核通知用户进程
    用户进程处理数据
    select:监视文件描述符分三类
        1)writefs 可写
        2)readfs  可读
        3)exceptfs异常
    文件描述符:32位计算机上1024个,64位监视2048个

 多线程服务器实例:

import threading
from socket import socket, SOCK_STREAM, AF_INET

ADDR = ("",1234)
BUFFERSIZE = 1024
tcp_server_sock = socket(AF_INET,SOCK_STREAM)
tcp_server_sock.bind(ADDR) #绑定端口IP
tcp_server_sock.listen()

def handle(sock, addr):
    while True:
        data = sock.recv(BUFFERSIZE).decode() #接受数据
        if not data:
            break
        print('收到信息:{}'.format(data))
        sock.send('{} {}'.format(
            '[threading-server]', data
        ).encode())
    sock.close()
    print('{}已关闭'.format(addr))
def main():
    print('等待客户端的连接。。。')
    while True:
        try:
            tcp_extension_sock,addr = tcp_server_sock.accept()
        except KeyboardInterrupt:
            break
        t = threading.Thread(
            target=handle,args=(tcp_extension_sock,addr)
        )
        t.start()
    print('\nExit')
    tcp_server_sock.close()

if __name__ == '__main__':
    main()
select:监视文件描述符分三类
    1)writefs 可写
    2)readfs  可读
    3)exceptfs异常
文件描述符:32位计算机上1024个,64位监视2048个
import select,time
from socket import socket, AF_INET, SOCK_STREAM

ADDR = ('',1234)
tcp_server_sock = socket(AF_INET,SOCK_STREAM)
tcp_server_sock.setblocking(False)
tcp_server_sock.bind(ADDR)
tcp_server_sock.listen()
# 创建三个列表作为select参数:等待读取、等待发送、等待异常
rlist = [tcp_server_sock]
wlist = []
xlist = []

print('Waiting for connection...')

while True:
    print('---------------------')
    # 文件描述符是操作文件返回句柄的编号,唯一
    print('rlist:',['套接字FD:{}'.format(s.fileno()) for s in rlist])
    print('wlist:', ['套接字FD:{}'.format(s.fileno()) for s in wlist])
    try:
        t = select.select(rlist,wlist,xlist)
        readble,writeble,exceptional = t
    except KeyboardInterrupt:
        break
    # 处理就绪的套接字
    for sock in readble:
        if sock is tcp_server_sock:
            tcp_extension_sock,addr = sock.accept()
            print('收到连接:{}'.format(addr))
            tcp_extension_sock.setblocking(False)
            rlist.append(tcp_extension_sock)
        else:
            data = sock.recv(1024)
            if data:
                print('收到数据:{}'.format(data.decode()))
                if sock not in wlist:
                    wlist.append(sock)
                else:
                    rlist.remove(sock)
                    sock.close()

    for sock in writeble:
        print('Server send ...')
        sock.send("{}".format(time.ctime()).encode())
        wlist.remove(sock)

    for sock in exceptional:
        print('Exceptional sock',sock)
        rlist.remove(sock)
        if sock in wlist:
            wlist.remove(sock)
        sock.close()

print('\nEnd')
tcp_server_sock.close()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Top Secret

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值