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中编写ORM框架的入门指引
Apr 29 Python
python超简单解决约瑟夫环问题
May 12 Python
Python爬取附近餐馆信息代码示例
Dec 09 Python
Python查找文件中包含中文的行方法
Dec 19 Python
Python根据当前日期取去年同星期日期
Apr 14 Python
python实现网站微信登录的示例代码
Sep 18 Python
Python: 传递列表副本方式
Dec 19 Python
Python 实现判断图片格式并转换,将转换的图像存到生成的文件夹中
Jan 13 Python
django 数据库 get_or_create函数返回值是tuple的问题
May 15 Python
Python中zipfile压缩文件模块的基本使用教程
Jun 14 Python
Python map及filter函数使用方法解析
Aug 06 Python
5行Python代码实现一键批量扣图
Jun 29 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模拟post行为代码总结(POST方式不是绝对安全)
2012/02/22 PHP
PHP中单引号与双引号的区别分析
2014/08/19 PHP
PHP实现利用MySQL保存session的方法
2014/08/23 PHP
PHP登录验证功能示例【用户名、密码、验证码、数据库、已登陆验证、自动登录和注销登录等】
2019/02/25 PHP
javascript基础第一章 JavaScript与用户端
2010/07/22 Javascript
Knockoutjs的环境搭建教程
2012/11/26 Javascript
javascript实现信息的显示和隐藏如注册页面
2013/12/03 Javascript
javascript中局部变量和全局变量的区别详解
2015/02/27 Javascript
jquery实现很酷的网页顶部图标下拉菜单效果
2015/08/22 Javascript
详解js中构造流程图的核心技术JsPlumb(2)
2015/12/08 Javascript
基于jQuery仿淘宝产品图片放大镜特效
2020/10/19 Javascript
js转换对象为xml
2017/02/17 Javascript
原生js实现放大镜特效
2017/03/08 Javascript
理解Angular的providers给Http添加默认headers
2017/07/04 Javascript
vue采用EventBus实现跨组件通信及注意事项小结
2018/06/14 Javascript
详解如何在vue项目中使用eslint+prettier格式化代码
2018/11/10 Javascript
Vue递归组件+Vuex开发树形组件Tree--递归组件的简单实现
2019/04/01 Javascript
详解ng-alain动态表单SF表单项设置必填和正则校验
2019/06/11 Javascript
ant-design-vue按需加载的坑的解决
2020/05/14 Javascript
js实现随机点名功能
2020/12/23 Javascript
python定时检查启动某个exe程序适合检测exe是否挂了
2013/01/21 Python
python 自定义对象的打印方法
2019/01/12 Python
简单了解django缓存方式及配置
2019/07/19 Python
Python将视频或者动态图gif逐帧保存为图片的方法
2019/09/10 Python
python中的subprocess.Popen()使用详解
2019/12/25 Python
Win10下用Anaconda安装TensorFlow(图文教程)
2020/06/18 Python
python3 os进行嵌套操作的实例讲解
2020/11/19 Python
佳能德国网上商店:Canon德国
2017/03/18 全球购物
英国足球店:UK Soccer Shop
2017/11/19 全球购物
什么是网络协议
2016/04/07 面试题
2014年学校德育工作总结
2014/12/05 职场文书
2015年小学教导处工作总结
2015/05/26 职场文书
独生子女证明范本
2015/06/19 职场文书
人民调解协议书
2016/03/21 职场文书
《好妈妈胜过好老师》:每个孩子的优秀都是有源头的
2020/01/03 职场文书
redis调用二维码时的不断刷新排查分析
2022/04/01 Redis