io 操作
'''
IO多路复用
I/O(input/output),即输入/输出端口。每个设备都会有一个专用的I/O地址,用来处理自己的输入输出信息首先什么是I/O:
I/O分为磁盘io和网络io,这里说的是网络io
IO多路复用:
I/O多路复用指:通过一种机制,可以监视多个描述符(socket),一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
Linux
Linux中的 select,poll,epoll 都是IO多路复用的机制。
Linux下网络I/O使用socket套接字来通信,普通I/O模型只能监听一个socket,而I/O多路复用可同时监听多个socket.
I/O多路复用避免阻塞在io上,原本为多进程或多线程来接收多个连接的消息变为单进程或单线程保存多个socket的状态后轮询处理.
Python
Python中有一个select模块,其中提供了:select、poll、epoll三个方法,分别调用系统的 select,poll,epoll 从而实现IO多路复用。
对于select模块操作的方法:
句柄列表11, 句柄列表22, 句柄列表33 = select.select(句柄序列1, 句柄序列2, 句柄序列3, 超时时间)
参数: 可接受四个参数(前三个必须)
返回值:三个列表
select方法用来监视文件句柄,如果句柄发生变化,则获取该句柄。
1、当 参数1 序列中的句柄发生可读时(accetp和read),则获取发生变化的句柄并添加到 返回值1 序列中
2、当 参数2 序列中含有句柄时,则将该序列中所有的句柄添加到 返回值2 序列中
3、当 参数3 序列中的句柄发生错误时,则将该发生错误的句柄添加到 返回值3 序列中
4、当 超时时间 未设置,则select会一直阻塞,直到监听的句柄发生变化
5、当 超时时间 = 1时,那么如果监听的句柄均无任何变化,则select会阻塞 1 秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行
'''
服务端:
sk1 = socket.socket()
sk1.bind(("127.0.0.1", 8001))
sk1.listen()
inpu = [sk1, ]
while True:
r_list, w_list, e_list = select.select(inpu, [], [], 1)
for sk in r_list:
if sk == sk1:
conn, address = sk.accept()
inpu.append(conn)
else:
try:
ret = str(sk.recv(1024), encoding="utf-8")
sk.sendall(bytes(ret + "hao", encoding="utf-8"))
except Exception as ex:
inpu.remove(sk)
客户端
import socket
obj = socket.socket()
obj.connect(('127.0.0.1', 8001))
while True:
inp = input("Please(q\退出):\n>>>")
obj.sendall(bytes(inp, encoding="utf-8"))
if inp == "q":
break
ret = str(obj.recv(1024), encoding="utf-8")
print(ret)
#服务端:
import socket
sk1 = socket.socket()
sk1.bind(("127.0.0.1", 8001))
sk1.listen()
inputs = [sk1]
import select
message_dic = {}
outputs = []
while True:
r_list, w_list, e_list = select.select(inputs, [], inputs, 1)
print("正在监听的socket对象%d" % len(inputs))
print(r_list)
for sk1_or_conn in r_list:
if sk1_or_conn == sk1:
conn, address = sk1_or_conn.accept()
inputs.append(conn)
message_dic[conn] = []
else:
try:
data_bytes = sk1_or_conn.recv(1024)
data_str = str(data_bytes, encoding="utf-8")
sk1_or_conn.sendall(bytes(data_str + "好", encoding="utf-8"))
except Exception as ex:
inputs.remove(sk1_or_conn)
else:
data_str = str(data_bytes, encoding="utf-8")
message_dic[sk1_or_conn].append(data_str)
outputs.append(sk1_or_conn)
for conn in w_list:
recv_str = message_dic[conn][0]
del message_dic[conn][0]
conn.sendall(bytes(recv_str + "好", encoding="utf-8"))
for sk in e_list:
inputs.remove(sk)
客户端:
import socket
obj = socket.socket()
obj.connect(('127.0.0.1', 8001))
while True:
inp = input("Please(q\退出):\n>>>")
obj.sendall(bytes(inp, encoding="utf-8"))
if inp == "q":
break
ret = str(obj.recv(1024), encoding="utf-8")
print(ret)
多任务异步携程01
import requests
import asyncio
import time
star=time.time()
urls=[
'http://127.0.0.1:5000/bobo','http://127.0.0.1:5000/jay','http://127.0.0.1:5000/tom'
]
async def get_page(url):
print('正在下载:',url)
#rewuests.get 是基于同步,必须使用基于异步的网络模块进行指定的url的请求
#aiohttp:基于异步网络请求的模块
respon=requests.get(url).text
print('下载完毕:',url)
tasks=[]
for url in urls:
c=get_page(url)
task=asyncio.ensure_future(c)
tasks.append(task)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
end=time.time()
print('总耗时',end-star)
'''
Fuction:客户端发送图片和数据
Date:
Author:mxh
'''
###客户端client.py
import socket
import os
import sys
import struct
def sock_client_image():
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 6666)) # 服务器和客户端在不同的系统或不同的主机下时使用的ip和端口,首先要查看服务器所在的系统网卡的ip
# s.connect(('127.0.0.1', 6666)) #服务器和客户端都在一个系统下时使用的ip和端口
except socket.error as msg:
print(msg)
print(sys.exit(1))
filepath = input('input the file: ') # 输入当前目录下的图片名 xxx.jpg
fhead = struct.pack(b'128sq', bytes(os.path.basename(filepath), encoding='utf-8'),
os.stat(filepath).st_size) # 将xxx.jpg以128sq的格式打包
s.send(fhead)
fp = open(filepath, 'rb') # 打开要传输的图片
while True:
data = fp.read(1024) # 读入图片数据
if not data:
print('{0} send over...'.format(filepath))
break
s.send(data) # 以二进制格式发送图片数据
s.close()
# break #循环发送
if __name__ == '__main__':
sock_client_image()
###服务器端server.py
import socket
import os
import sys
import struct
def socket_service_image():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# s.bind(('127.0.0.1', 6666))
s.bind(('127.0.0.1', 6666))
s.listen(10)
except socket.error as msg:
print(msg)
sys.exit(1)
print("Wait for Connection.....................")
while True:
sock, addr = s.accept() # addr是一个元组(ip,port)
deal_image(sock, addr)
def deal_image(sock, addr):
print("Accept connection from {0}".format(addr)) # 查看发送端的ip和端口
while True:
fileinfo_size = struct.calcsize('128sq')
print('fileinfo_size is', fileinfo_size)
buf = sock.recv(fileinfo_size) # 接收图片名
print('buf is ', buf)
if buf:
filename, filesize = struct.unpack('128sq', buf)
print('filename ,filesize is', filename.decode(), filesize)
fn = filename.decode().strip('\x00')
print('fn is ', fn)
new_filename = os.path.join('./',
'new_' + fn) # 在服务器端新建图片名(可以不用新建的,直接用原来的也行,只要客户端和服务器不是同一个系统或接收到的图片和原图片不在一个文件夹下)
recvd_size = 0
fp = open(new_filename, 'wb')
while not recvd_size == filesize:
if filesize - recvd_size > 1024:
data = sock.recv(1024)
recvd_size += len(data)
else:
data = sock.recv(1024)
recvd_size = filesize
print('data is', data)
fp.write(data) # 写入图片数据
fp.close()
sock.close()
break
if __name__ == '__main__':
socket_service_image()
import socket
import sys
#客户端
def socket_client():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 6666))
except socket.error as msg:
print(msg)
sys.exit(1)
print(s.recv(1024)) # 目的在于接受:Accept new connection from (...
while 1:
data = input('please input work: ').encode()
s.send(data)
print('aa', s.recv(1024))
if data == 'exit':
break
s.close()
if __name__ == '__main__':
socket_client()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」