1. 功能:
    1、使用SELECTSELECTORS模块实现并发简单版FTP
    2、允许多用户并发上传下载文件
    环境:
      python 3.5
    特性:
      select 实现并发效果
    运行:
    get 文件名 #从服务器下载文件
    put 文件名 #向服务器上传文件
    helps #帮助信息
    其他命令 #变大写返回给客户端
    主要知识点:
    os模块的应用
    json模块的运用
    select模块的运用
    socket通信
    queue数据交互
    粘包
    原理:
    这个程序通过select实现了并发,主要原理为它通过一个select()系统调用来监视多个文件描述符的数组(在linux中一切事物皆文
    件,块设备,socket连接等。),当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位(变成ready),使得进程
    可以获得这些文件描述符从而进行后续的读写操作(select会不断监视网络接口的某个目录下有多少文件描述符变成ready状态【在
    网络接口中,过来一个连接就会建立一个'文件'】,变成ready状态后,select就可以操作这个文件描述符了)。
    通过不同链接的交替,实现并发效果。
    主要代码:
  1. readable, writeable, exeptional = select.select(inputs,outputs,inputs) #如果没有任何fd就绪,那程序就会一直阻塞在这里
  2. # select中第1个参数表示inputs中发生变化的句柄放入readable。
  3. # select中第2个参数表示outputs中的值原封不动的传递给writeable。
  4. # select中第3个参数表示inputs中发生错误的句柄放入exeptional.
  1.  
  1. import json
  2. import select
  3. import socket
  4. import queue
  5. import os
  6.  
  7. os.chdir(os.pardir)
  8. server = socket.socket()
  9. server_addr = ("localhost",1000)
  10. server.bind(server_addr)
  11. server.listen(7)
  12. inputs = [server,]
  13. outputs = []
  14. message_queue ={}
  15.  
  16. while True:
  17. readable,writeable,exeptional = select.select(inputs,outputs,inputs)
  18. #
  19. # 存放所有的活动
  20. for sock in readable:
  21. if sock is server:
  22. conn, client_addr = sock.accept()
  23. inputs.append(conn)
  24. message_queue[conn] = queue.Queue() #为防阻塞,先把信息存入队列
  25. else:
  26. data = sock.recv(1024)
  27. if data:
  28. message_queue[sock].put(data)
  29. if sock not in outputs:
  30. outputs.append(sock)
  31.  
  32. else:
  33. if sock in outputs:
  34. outputs.remove(sock)
  35. inputs.remove(sock)
  36. del message_queue[sock]
  37. #
  38. # 存放连接信息
  39. #
  40. for sock in writeable:
  41. try:
  42. cmd = message_queue[sock].get_nowait()
  43. except queue.Empty:
  44. outputs.remove(sock)
  45. else:
  46. print("recv data:", cmd)
  47. data = json.loads(cmd.decode())
  48. if data.get('action') is not None:
  49. #
  50. # 上传文件
  51. if data['action'] == 'put':
  52. # client sends file to server
  53. file_obj = open('data/'+data['filename'], 'wb')
  54. received_size = 0
  55. sock.send(b'')
  56. while True:
  57. if received_size == data['size']:
  58. break
  59. recv_data = sock.recv(1024)
  60. file_obj.write(recv_data)
  61. received_size += len(recv_data)
  62. if received_size == data['size']:
  63. print('Successfully received file ', data['filename'])
  64. file_obj.close()
  65. #
  66. # 下载文件
  67. elif data['action'] == 'get':
  68. if os.path.isfile(data['filename']):
  69. data['file_size'] = os.path.getsize(data['filename'])
  70. data['ERROR'] = ''
  71. else:
  72. data['ERROR'] = '' #ERROR标识
  73. sock.send(json.dumps(data).encode())
  74. if os.path.isfile(data['filename']):
  75. if sock.recv(1) == b'': #等待客户端响应,防粘包
  76. if data['ERROR'] == '':
  77. file_obj = open(data['filename'], 'rb')
  78. for line in file_obj:
  79. sock.send(line)
  80. #
  81. # 其他命令
  82. else:
  83. data['cmd'] = data['cmd'].upper()
  84. sock.send(json.dumps(data).encode())
  85.  
  86. #
  87. # 错误链接
  88. for sock in exeptional:
  89. if sock in outputs:
  90. outputs.remove(sock)
  91. inputs.remove(sock)
  92. del message_queue[sock]

server端

  1.  
  1. import json
  2. import socket
  3. import os
  4.  
  5. os.chdir(os.pardir)
  6. server_address = ('localhost', 1000)
  7. sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  8. sock.connect(server_address)
  9. print('''------Welcome!!-----
  10. (helps:帮助信息)''')
  11. while True:
  12. cmd = input(">>>").strip()
  13. cmd_list = cmd.split()
  14. #
  15. #上传文件
  16. if cmd_list[0] == 'put':
  17. if len(cmd_list) == 1: #命令不能识别
  18. print('No filename follows after put cmd!')
  19. continue
  20. filename = 'data/'+cmd_list[1] #将所有的文件都归入data文件夹
  21. if os.path.isfile(filename):
  22. file_obj = open(filename,'rb')
  23. base_filename = filename.split('/')[-1]
  24. data_header = {
  25. 'action':'put',
  26. 'filename':base_filename,
  27. 'size':os.path.getsize(filename)
  28. }
  29. sock.send(json.dumps(data_header).encode())
  30. if sock.recv(1) == b'': #防止粘包
  31. for line in file_obj:
  32. sock.send(line)
  33. file_obj.close()
  34. print('put all file..')
  35. else:
  36. print('File is not valid')
  37. continue
  38. #
  39. # 下载文件
  40. elif cmd_list[0] == 'get':
  41. if len(cmd_list) == 1:
  42. print('No filename follows after get cmd!')
  43. continue
  44. filename = 'data/'+ cmd_list[1]
  45. data_header = {
  46. 'action':'get',
  47. 'filename':filename,
  48. 'ERROR':''
  49. }
  50. sock.send(json.dumps(data_header).encode())
  51. data_header = json.loads(sock.recv(1024).decode())
  52. if data_header['ERROR'] == '':
  53. file_obj = open(data_header['filename'], 'wb')
  54. received_size = 0
  55. sock.send(b'')
  56. while True:
  57.  
  58. if received_size == data_header['file_size']:
  59. break
  60. recv_data = sock.recv(1024)
  61. file_obj.write(recv_data)
  62. received_size += len(recv_data)
  63.  
  64. print('Successfully received file ', data_header['filename'])
  65. file_obj.close()
  66. #
  67. # 帮助信息
  68. elif cmd_list[0] == 'helps':
  69. print('''
  70. put 文件名 #上传文件
  71. get 文件名 #下载文件
  72. 其他命令 #返回大写''')
  73. #
  74. # 其他命令
  75. else:
  76. data_header = {
  77. 'action':'else',
  78. 'cmd':cmd
  79. }
  80. sock.send(json.dumps(data_header).encode())
  81. data_recv = json.loads(sock.recv(1024).decode())
  82. print(data_recv['cmd'])

client端

  1.  

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. Java面试——线程池

    1.类比介绍 假如有一个工厂,工厂里面有10个工人,每个工人同时只能做一件任务. 因此只要当10个工人中有工人是空闲的,来了任务就分配给空闲的工人做: 当10个工人都有任务在做时,如果还来了任务,就把 ...

  2. threading join用法

    join():在子线程完成运行之前,这个子线程的父线程将一直被阻塞 import threading #线程import time def Beijing(n): print('Beijing tim ...

  3. 30_react_router基本使用

    项目结构: import React from 'react' import {render} from 'react-dom' import {BrowserRouter} from 'react- ...

  4. 应用脚手架创建一个React项目

    安装脚手架,这里会自动安装到你的nodejs里面 npm install create-react-app -g 进入创建目录 我这里创建一个为 react03的项目,等待下载..... create ...

  5. C# 导出dataGridView中的值到Excel

    C# 怎么导出dataGridView中的值到Excel 1 2 3 4 5 6 在系统应用过程中,数据是系统的核心.如果直接在应用软件中看数据,有时也有些不便,所以就会把系统数据转换成Excel格式 ...

  6. Unity中的点击,长按,划动

    public void GetClickType() { if(Input.GetMouseButtonDown(0)) { if(isGetBeginPos) { beginPosition = I ...

  7. cdn节点自定义防CC代码在哪里抄

    1. 登陆节点的3311后台 1. http redirect(普通) HTTP/1.1 302 FOUNDConnection: keep-aliveLocation: {{url}} <ht ...

  8. 十、Strategy 策略模式

    需求:使用不同的算法解决相同的问题 设计原理: 代码清单: 接口 Strategy public interface Strategy { public abstract Hand nextHand( ...

  9. Python设计模式 - 基础 - 封装 & 继承 & 多态

    面向对象的核心是对象,世间万物都可以看作对象,任何一个对象都可以通过一系列属性和行为来描述,可以包含任意数量和类型的数据或操作.类是用来描述具有相同属性和方法的所有对象的集合.类通常是抽象化的概念,而 ...

  10. oracle可重复执行脚本(添加字段)

    --添加债券期限字段 declare cn integer; begin cn := 0; select count(*) into cn from user_tab_cols t where t.t ...