目录
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()