局域网传输还在用飞鸽?还在用QQ,其实Python也可以实现类似的功能!Python基于scoket实现多路复用TCP局域网文件传输

1.IO是什么?

⦁定义

在内存中存在数据交换的操作
和终端交互:input, output
和磁盘交互:read, write
和网络交互:recv, send

①IO密集型:在程序当中存在大量的IO,而CPU的运算较少,消耗CPU资源小,耗时长,效率不高
②计算密集型:在运算中存在大量计算,IO行为较少,CPU消耗大,执行速度快

⦁ 阻塞IO

定义:在执行IO操作时由于不满足某些条件形成的阻塞形态
效率:阻塞IO是一种效率很低的IO,逻辑简单。

⦁ 非阻塞IO

定义:通过修改IO的属性行为,使原本阻塞的IO变为非阻塞的状态
修改方法:
sockf.setblocking(bool)
功能:设置套接字为非阻塞IO
参数:True为阻塞,False为非阻塞

Sockf.settimeout(sec)
功能:超时检测,阻塞等待的时间,超时后不再阻塞
参数:超时时间,以秒为单位

2.IO多路复用

定义

同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO,以此形成可以同时处理多个IO的行为。避免一个IO阻塞造成其他IO无法执行,提高IO执行效率。
具体方案:①select: windows/linux/unix
②poll: linux/unix
③epoll: linux

select具体用法

①导入: from select import select
②监控IO:
rs,ws,xs = select(rlist,wlist,xlist)
功能:监控多个IO事件,阻塞等待IO发生
参数:rlist 列表,关注的等待发生的IO事件
wlist 列表,要主动处理的IO事件
xlist 列表,发生异常时要处理的IO事件
返回值:
rs: 列表,rlist中准别就绪的IO
ws: 列表,wlist中准别就绪的IO
xs: 列表, xlist中准别就绪的IO
③注意:

  • wlist 中如果有IO事件,select 会立即返回为ws
    *处理事件过程找那个不要出现死循环等长期占有服务端的情况
    *IO多路复用消耗资源较少,效率较高
  • 套接字获取地址的方法:
    sockfd.getpeername() 返回一个元组: (ip,port)

3.实现多路复用局域网文件传输

server.py

from select import *
from socket import *#导入模块
from FileOperation import *

ip_address = "0.0.0.0"#设置IPV4地址
port = 8097#设置端口
num = 3#设置监听数量
addrs = []

server = socket(
	family=AF_INET,
	type = SOCK_STREAM,
	proto = 0
	)

server.bind((ip_address,port))
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,True)
#SO_REUSEADDR指的是一个网络地址在短时间重复利用
server.listen(num)
print("server is listening to the port:%d"%port)
print("server can be connected for %d clients at the same time "%num)
print("------------------------------------")

rlist = [server]#存放关注的,等待发生的IO事件
wlist = []#存放主动处理的IO事件
xlist = []#存放发生异常的事件


while True:
	rs,ws,xs = select(rlist,wlist,xlist)
	for i in rs:#遍历准备就绪的IO事件,如果准备就绪的IO事件i,如果i等于服务器server时,有客户端连接上来了。
		if i is server:
			coon,addr = i.accept()#连接
			rlist.append(coon)
			print(addr,"is connected......")
			addrs.append(addr)
		else:#如果i等于连接套接字类型,那就去接收
			data = i.recv(102400)#阻塞等待发送消息
			msg = data
			add_file("./vmware-1.exe",msg)
				
			if msg == "quit":#客户端要求断开连接
				rlist.remove(i)
				i.close()
				continue
			else:
				i.send(b"ok")#向客户端反馈OK信息
server.close()

client.py

from socket import *#导入socket库
import time
from FileOperation import *

global server_ip
global server_port

server_ip = "192.168.75.1"#这里使用cmd查看主机ipv4地址
server_port = 8097

client = socket(
	family = AF_INET,
	type = SOCK_STREAM,
	proto = 0)


while True:
	try:#服务端未打开时的异常
		client.setsockopt(SOL_SOCKET,SO_REUSEADDR,True)
		client.connect((server_ip,server_port))
	except:
		print("您是不是远离服务器了,靠近后再试一试!")
		server_ip = input("如果ip接口输入错误,请在这里重试:")
		server_port = input("如果ip端口输入错误,请在这里重试:")
		print("正在重试中...")
		print(server_ip)
		print(server_port)
	else:
		break

while True:
	msg,read_bool = open_file("vmware.exe")
	client.send(msg)
	if msg == "quit":
		break

	data = client.recv(1024)
	msg = data.decode()
	print("server:%s"%msg)


client.close()

FileOperation.py

def open_file(dir):
	ReadBool = None
	msg = None
	try:
		with open(dir,"rb")as f:
			msg = f.read()
	except:
		pass
	else:
		ReadBool = True

	return msg,ReadBool

def write_file(dir,message):
	WriteBool = None
	msg = None
	try:
		with open(dir,"wb+")as f:
			f.write(message)
			f.close()
	except:
		pass
	else:
		WriteBool = True

	return msg,WriteBool

def add_file(dir,message):
	AddBool = None
	msg = None
	try:
		with open(dir,"ab+")as f:
			f.write(message)
			f.close()
	except:
		pass
	else:
		AddBool = True

	return msg,AddBool

注意事项

  1. msg,read_bool = open_file("vmware.exe")
    是作者电脑中包含的文件,当使用TCP传输时,要记得将这个地方换成电脑中的可读取文件,不然程序会报错
  2. server_ip = "192.168.75.1"
    这里要转换为服务器的ipv4地址
  3. 要先打开server.py文件,再打开client.py。最好是在命令行运行

运行效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

地摊主老袁

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

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

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

打赏作者

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

抵扣说明:

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

余额充值