Python实现的FTP通信客户端与服务器端功能示例


Posted in Python onMarch 28, 2018

本文实例讲述了Python实现的FTP通信客户端与服务器端功能。分享给大家供大家参考,具体如下:

一 代码

1、服务端代码

import socket
import threading
import os
import struct
#用户账号、密码、主目录
#也可以把这些信息存放到数据库中
users = {'zhangsan':{'pwd':'zhangsan1234', 'home':r'c:\python 3.5'},
     'lisi':{'pwd':'lisi567', 'home':'c:\\'}}
def server(conn,addr, home):
  print('新客户端:'+str(addr))
  #进入当前用户主目录
  os.chdir(home)
  while True:
    data = conn.recv(100).decode().lower()
    #显示客户端输入的每一条命令
    print(data)
    #客户端退出
    if data in ('quit', 'q'):
      break
    #查看当前文件夹的文件列表
    elif data in ('list', 'ls', 'dir'):
      files = str(os.listdir(os.getcwd()))
      files = files.encode()
      conn.send(struct.pack('I', len(files)))
      conn.send(files)
    #切换至上一级目录
    elif ''.join(data.split()) == 'cd..':
      cwd = os.getcwd()
      newCwd = cwd[:cwd.rindex('\\')]
      #考虑根目录的情况
      if newCwd[-1] == ':':
        newCwd += '\\'
      #限定用户主目录
      if newCwd.lower().startswith(home):
        os.chdir(newCwd)
        conn.send(b'ok')
      else:
        conn.send(b'error')
    #查看当前目录
    elif data in ('cwd', 'cd'):
      conn.send(str(os.getcwd()).encode())
    elif data.startswith('cd '):
      #指定最大分隔次数,考虑目标文件夹带有空格的情况
      #只允许使用相对路径进行跳转
      data = data.split(maxsplit=1)
      if len(data) == 2 and os.path.isdir(data[1]) \
        and data[1]!=os.path.abspath(data[1]):
        os.chdir(data[1])
        conn.send(b'ok')
      else:
        conn.send(b'error')
    #下载文件
    elif data.startswith('get '):
      data = data.split(maxsplit=1)
      #检查文件是否存在
      if len(data) == 2 and os.path.isfile(data[1]):
        conn.send(b'ok')
        fp = open(data[1], 'rb')
        while True:
          content = fp.read(4096)
          #发送文件结束
          if not content:
            conn.send(b'overxxxx')
            break
          #发送文件内容
          conn.send(content)
          if conn.recv(10) == b'ok':
            continue
        fp.close()
      else:
        conn.send(b'no')
    #无效命令
    else:
      pass
  conn.close()
  print(str(addr)+'关闭连接')
#创建Socket,监听本地端口,等待客户端连接
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 10600))
sock.listen(5)
while True:
  conn, addr = sock.accept()
  #验证客户端输入的用户名和密码是否正确
  userId, userPwd = conn.recv(1024).decode().split(',')
  if userId in users and users[userId]['pwd'] == userPwd:
    conn.send(b'ok')
    #为每个客户端连接创建并启动一个线程,参数为连接、客户端地址、客户主目录
    home = users[userId]['home']
    t = threading.Thread(target=server, args=(conn,addr,home))
    t.daemon = True
    t.start()
  else:
    conn.send(b'error')

2、客户端代码

import socket
import sys
import re
import struct
import getpass
def main(serverIP):
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  sock.connect((serverIP, 10600))
  userId = input('请输入用户名:')
  #使用getpass模块的getpass()方法获取密码,不回显
  userPwd = getpass.getpass('请输入密码:')
  message = userId+','+userPwd
  sock.send(message.encode())
  login = sock.recv(100)
  #验证是否登录成功
  if login == b'error':
    print('用户名或密码错误')
    return
  #整数编码大小
  intSize = struct.calcsize('I')
  while True:
    #接收客户端命令,其中##>是提示符
    command = input('##> ').lower().strip()
    #没有输入任何有效字符,提前进入下一次循环,等待用户继续输入
    if not command:
      continue
    #向服务端发送命令
    command = ' '.join(command.split())
    sock.send(command.encode())
    #退出
    if command in ('quit', 'q'):
      break
    #查看文件列表
    elif command in ('list', 'ls', 'dir'):
      loc_size = struct.unpack('I', sock.recv(intSize))[0]
      files = eval(sock.recv(loc_size).decode())
      for item in files:
        print(item)
    #切换至上一级目录
    elif ''.join(command.split()) == 'cd..':
      print(sock.recv(100).decode())
    #查看当前工作目录
    elif command in ('cwd', 'cd'):
      print(sock.recv(1024).decode())
    #切换至子文件夹
    elif command.startswith('cd '):
      print(sock.recv(100).decode())
    #从服务器下载文件
    elif command.startswith('get '):
      isFileExist = sock.recv(20)
      #文件不存在
      if isFileExist != b'ok':
        print('error')
      #文件存在,开始下载
      else:
        print('downloading.', end='')
        fp = open(command.split()[1], 'wb')
        while True:
          print('.', end='')
          data = sock.recv(4096)
          if data == b'overxxxx':
            break
          fp.write(data)
          sock.send(b'ok')
        fp.close()
        print('ok')
    #无效命令
    else:
      print('无效命令')
  sock.close()
if __name__ == '__main__':
  if len(sys.argv) != 2:
    print('Usage:{0} serverIPAddress'.format(sys.argv[0]))
    exit()
  serverIP = sys.argv[1]
  if re.match(r'^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$', serverIP):
    main(serverIP)
  else:
    print('服务器地址不合法')
    exit()

二 运行结果

客户端运行结果

Python实现的FTP通信客户端与服务器端功能示例

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
python使用三角迭代计算圆周率PI的方法
Mar 20 Python
python+selenium实现京东自动登录及秒杀功能
Nov 18 Python
python回调函数中使用多线程的方法
Dec 25 Python
Python批处理更改文件名os.rename的方法
Oct 26 Python
python微信好友数据分析详解
Nov 19 Python
Python中如何导入类示例详解
Apr 17 Python
Python TestCase中的断言方法介绍
May 02 Python
django表单的Widgets使用详解
Jul 22 Python
Python爬虫 urllib2的使用方法详解
Sep 23 Python
PyCharm汉化安装及永久激活详细教程(靠谱)
Jan 16 Python
keras 多任务多loss实例
Jun 22 Python
Django框架安装及项目创建过程解析
Sep 14 Python
Python实现发送与接收邮件的方法详解
Mar 28 #Python
Python实现线程状态监测简单示例
Mar 28 #Python
python实现朴素贝叶斯分类器
Mar 28 #Python
详解Python中where()函数的用法
Mar 27 #Python
Django基于ORM操作数据库的方法详解
Mar 27 #Python
利用Python批量提取Win10锁屏壁纸实战教程
Mar 27 #Python
Django学习笔记之ORM基础教程
Mar 27 #Python
You might like
PHP数组的交集array_intersect(),array_intersect_assoc(),array_inter_key()函数的小问题
2011/05/29 PHP
PHP函数strip_tags的一个bug浅析
2014/05/22 PHP
php和editplus正则表达式去除空白行
2015/04/17 PHP
PHP使用缓存即时输出内容(output buffering)的方法
2015/08/03 PHP
PHP CURL post数据报错 failed creating formpost data
2016/10/16 PHP
javascript获取下拉列表框当中的文本值示例代码
2013/07/31 Javascript
Jquery AJAX POST与GET之间的区别
2013/11/14 Javascript
不提示直接关闭网页窗口的JS示例代码
2013/12/17 Javascript
jQuery中DOM树操作之使用反向插入方法实例分析
2015/01/23 Javascript
Ajax中解析Json的两种方法对比分析
2015/06/25 Javascript
JS选取DOM元素的简单方法
2016/07/08 Javascript
JS获取和修改元素样式的实例代码
2016/08/06 Javascript
Vue.js实现一个自定义分页组件vue-paginaiton
2016/09/05 Javascript
将鼠标焦点定位到文本框最后(代码分享)
2017/01/11 Javascript
详解JS模块导入导出
2017/12/20 Javascript
Vue.js结合bootstrap前端实现分页和排序效果
2018/12/29 Javascript
django中使用vue.js的要点总结
2019/07/07 Javascript
Vue中遍历数组的新方法实例详解
2019/07/21 Javascript
viewer.js实现图片预览功能
2020/06/24 Javascript
vue项目实现设置根据路由高亮对应的菜单项操作
2020/08/06 Javascript
vue cli 3.0通用打包配置代码,不分一二级目录
2020/09/02 Javascript
[52:03]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第三场 1月31日
2021/03/11 DOTA
python和shell实现的校验IP地址合法性脚本分享
2014/10/23 Python
python实践项目之监控当前联网状态详情
2019/05/23 Python
Python使用itcaht库实现微信自动收发消息功能
2020/07/13 Python
在Pycharm中安装Pandas库方法(简单易懂)
2021/02/20 Python
中国首家奢侈品O2O网购平台:第五大道奢侈品网
2017/12/14 全球购物
英国最大的经认证的有机超市:Planet Organic
2018/02/02 全球购物
小学生防溺水广播稿
2014/01/12 职场文书
小学安全教育月活动总结
2014/07/07 职场文书
国际商务专业求职信
2014/07/15 职场文书
简历自荐信范文
2015/03/09 职场文书
2015年检验员工作总结范文
2015/04/30 职场文书
60句有关成长的名言
2019/09/04 职场文书
react国际化react-intl的使用
2021/05/06 Javascript
MYSQL优化之数据表碎片整理详解
2022/04/03 MySQL