SELECT版FTP

时间:2022-09-20 00:01:41
功能: 
1、使用SELECT或SELECTORS模块实现并发简单版FTP
2、允许多用户并发上传下载文件
环境:
  python 3.5
特性:
  select 实现并发效果
运行:
get 文件名 #从服务器下载文件
put 文件名 #向服务器上传文件
helps #帮助信息
其他命令 #变大写返回给客户端
主要知识点:
os模块的应用
json模块的运用
select模块的运用
socket通信
queue数据交互
粘包
原理:
这个程序通过select实现了并发,主要原理为它通过一个select()系统调用来监视多个文件描述符的数组(在linux中一切事物皆文
件,块设备,socket连接等。),当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位(变成ready),使得进程
可以获得这些文件描述符从而进行后续的读写操作(select会不断监视网络接口的某个目录下有多少文件描述符变成ready状态【在
网络接口中,过来一个连接就会建立一个'文件'】,变成ready状态后,select就可以操作这个文件描述符了)。
通过不同链接的交替,实现并发效果。
主要代码:
readable, writeable, exeptional = select.select(inputs,outputs,inputs) #如果没有任何fd就绪,那程序就会一直阻塞在这里
# select中第1个参数表示inputs中发生变化的句柄放入readable。
# select中第2个参数表示outputs中的值原封不动的传递给writeable。
# select中第3个参数表示inputs中发生错误的句柄放入exeptional.
 
 import json
import select
import socket
import queue
import os os.chdir(os.pardir)
server = socket.socket()
server_addr = ("localhost",1000)
server.bind(server_addr)
server.listen(7)
inputs = [server,]
outputs = []
message_queue ={} while True:
readable,writeable,exeptional = select.select(inputs,outputs,inputs)
#
# 存放所有的活动
for sock in readable:
if sock is server:
conn, client_addr = sock.accept()
inputs.append(conn)
message_queue[conn] = queue.Queue() #为防阻塞,先把信息存入队列
else:
data = sock.recv(1024)
if data:
message_queue[sock].put(data)
if sock not in outputs:
outputs.append(sock) else:
if sock in outputs:
outputs.remove(sock)
inputs.remove(sock)
del message_queue[sock]
#
# 存放连接信息
#
for sock in writeable:
try:
cmd = message_queue[sock].get_nowait()
except queue.Empty:
outputs.remove(sock)
else:
print("recv data:", cmd)
data = json.loads(cmd.decode())
if data.get('action') is not None:
#
# 上传文件
if data['action'] == 'put':
# client sends file to server
file_obj = open('data/'+data['filename'], 'wb')
received_size = 0
sock.send(b'')
while True:
if received_size == data['size']:
break
recv_data = sock.recv(1024)
file_obj.write(recv_data)
received_size += len(recv_data)
if received_size == data['size']:
print('Successfully received file ', data['filename'])
file_obj.close()
#
# 下载文件
elif data['action'] == 'get':
if os.path.isfile(data['filename']):
data['file_size'] = os.path.getsize(data['filename'])
data['ERROR'] = ''
else:
data['ERROR'] = '' #ERROR标识
sock.send(json.dumps(data).encode())
if os.path.isfile(data['filename']):
if sock.recv(1) == b'': #等待客户端响应,防粘包
if data['ERROR'] == '':
file_obj = open(data['filename'], 'rb')
for line in file_obj:
sock.send(line)
#
# 其他命令
else:
data['cmd'] = data['cmd'].upper()
sock.send(json.dumps(data).encode()) #
# 错误链接
for sock in exeptional:
if sock in outputs:
outputs.remove(sock)
inputs.remove(sock)
del message_queue[sock]

server端


 import json
import socket
import os os.chdir(os.pardir)
server_address = ('localhost', 1000)
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect(server_address)
print('''------Welcome!!-----
(helps:帮助信息)''')
while True:
cmd = input(">>>").strip()
cmd_list = cmd.split()
#
#上传文件
if cmd_list[0] == 'put':
if len(cmd_list) == 1: #命令不能识别
print('No filename follows after put cmd!')
continue
filename = 'data/'+cmd_list[1] #将所有的文件都归入data文件夹
if os.path.isfile(filename):
file_obj = open(filename,'rb')
base_filename = filename.split('/')[-1]
data_header = {
'action':'put',
'filename':base_filename,
'size':os.path.getsize(filename)
}
sock.send(json.dumps(data_header).encode())
if sock.recv(1) == b'': #防止粘包
for line in file_obj:
sock.send(line)
file_obj.close()
print('put all file..')
else:
print('File is not valid')
continue
#
# 下载文件
elif cmd_list[0] == 'get':
if len(cmd_list) == 1:
print('No filename follows after get cmd!')
continue
filename = 'data/'+ cmd_list[1]
data_header = {
'action':'get',
'filename':filename,
'ERROR':''
}
sock.send(json.dumps(data_header).encode())
data_header = json.loads(sock.recv(1024).decode())
if data_header['ERROR'] == '':
file_obj = open(data_header['filename'], 'wb')
received_size = 0
sock.send(b'')
while True: if received_size == data_header['file_size']:
break
recv_data = sock.recv(1024)
file_obj.write(recv_data)
received_size += len(recv_data) print('Successfully received file ', data_header['filename'])
file_obj.close()
#
# 帮助信息
elif cmd_list[0] == 'helps':
print('''
put 文件名 #上传文件
get 文件名 #下载文件
其他命令 #返回大写''')
#
# 其他命令
else:
data_header = {
'action':'else',
'cmd':cmd
}
sock.send(json.dumps(data_header).encode())
data_recv = json.loads(sock.recv(1024).decode())
print(data_recv['cmd'])

client端

														
		

SELECT版FTP的更多相关文章

  1. python作业Select版本FTP(第十周)

    SELECT版FTP: 使用SELECT或SELECTORS模块实现并发简单版FTP 允许多用户并发上传下载文件 思路解析: 1. 使用IO多路复用的知识使用SELECTORS封装好的SELECTOR ...

  2. SELECTORS模块实现并发简单版FTP

    环境:windows, python 3.5功能:使用SELECTORS模块实现并发简单版FTP允许多用户并发上传下载文件 结构:ftp_client ---| bin ---| start_clie ...

  3. jquery双向列表选择器select版

    这个是select版的,若想美化某些样式是不支持得,可以用div模拟版的,功能基本实现能用了,需要其他功能自己加上. div模拟版链接:http://www.cnblogs.com/tie123abc ...

  4. Android版Ftp服务端软件

    分享一款开发的Android版Ftp服务端软件,支持Android4.0及以上版本,可以实现局域网无线传输文件到手机,或者把手机上的多媒体文件分享到iPad等设备来扩展这些设备的存储空间,详情请见软件 ...

  5. java版ftp简易客户端(可以获取文件的名称及文件大小)

    java版ftp简易客户端(可以获取文件的名称及文件大小) package com.ccb.ftp; import java.io.IOException; import java.net.Socke ...

  6. IO多路复用版FTP

    需求: 实现文件上传及下载功能 支持多连接并发传文件 使用select or selectors 流程图 import socket import pickle import sys import t ...

  7. C# socket实践 - 简易版FTP(Server & Client)

    写了个简易版的ftp(服务器和客户端),运行效果如下图: click download下载中的UI: 原理:模仿正规ftp方式,分成2个socket连接:文本命令socket.数据信道socket. ...

  8. Serv-U精简版FTP服务端

    Window搭建自己的FTP,Serv-U是很不错的选择... 00.运行视图 注意: 此版本是绿色破解版,个人使用很便捷的.不建议商业使用... download: https://pan.baid ...

  9. 170404、java版ftp操作工具类

    package com.rick.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotF ...

随机推荐

  1. 数据结构作业——hash(字符串哈希)

    Hash Description 给定长度为 n ( n<=1000000)的字符串,字符串仅由小写字母的前 m ( m<=6) 个字符组成,请你计算出共有多少长度为 k( k<=6 ...

  2. shell 执行jar 的命令

    #!/bin/sh ############## #判断是否程序已启动 jappname='Test' mainclasspath="com.company.commontest.test& ...

  3. Objective-C中的浅拷贝和深拷贝

    浅拷贝 浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间.如: char* str = (char*)malloc(100); char* str2 = str; 浅拷贝只是对对象 ...

  4. Microsoft Visual Studio小技巧

    main函数调试参数: Project -> Properties -> Configuration Properties -> Debugging 在Command Argumen ...

  5. windows下使用SQLPLUS制作BAT执行SQL文件

    假如你把需要的SQL操作信息等均放入到一个SQL文件中,需要制作一个bat文件来执行这个sql文件,那么你的bat文件中,在sqlplus登录语句后的信息不能换行,换行的话则执行登录sqlplus后就 ...

  6. hive的体系架构及安装

    1,什么是Hive? Hive是能够用类SQL的方式操作HDFS里面数据一个数据仓库的框架,这个类SQL我们称之为HQL(Hive Query Language) 2,什么是数据仓库? 存放数据的地方 ...

  7. hdu 4786 Fibonacci Tree(最小生成树)

    Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  8. WSMBT Modbus &amp&semi; WSMBS Modbus 控件及注册机

    先上注册机 点击下载 How to add the WSMBT control to the toolbox: On the Tools menu, click Choose Toolbox Item ...

  9. &lbrack;原创&rsqb;Javascript 利用mousetrap&period;js进行键盘事件操作

    我们日常开发中,会遇到js的键盘操作,例如回车提交表单之类的.或者按下某个键执行某个方法.无意中发现一个大小不到4K的js文件,它非常方便的操作键盘事件. 自己也尝试了一下:具体代码如下: 详情可以去 ...

  10. Controller传值到前端页面的几种方式

    一丶追加字符串传值 #region 02-追加字符串传值 /// <summary> /// 02-追加字符串传值 /// </summary> /// <returns ...