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的Bottle框架写一个简单的服务接口的示例
Aug 25 Python
听歌识曲--用python实现一个音乐检索器的功能
Nov 15 Python
python3.x实现发送邮件功能
May 22 Python
在python3中实现更新界面
Feb 21 Python
python 插入日期数据到Oracle实例
Mar 02 Python
numpy库reshape用法详解
Apr 19 Python
Python pip install如何修改默认下载路径
Apr 29 Python
Python3 requests模块如何模仿浏览器及代理
Jun 15 Python
Python 如何在字符串中插入变量
Aug 01 Python
python 使用三引号时容易犯的小错误
Oct 21 Python
matplotlib绘制多子图共享鼠标光标的方法示例
Jan 08 Python
Python实现简单得递归下降Parser
May 02 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
Amazon Prime Video平台《无限住人 -IMMORTAL-》2020年开始TV放送!
2020/03/06 日漫
详细介绍PHP应用提速面面观
2006/10/09 PHP
php中\r \r\n \t的区别示例介绍
2014/02/08 PHP
用正则获取指定路径文件的名称
2007/02/27 Javascript
JavaScript toFixed() 方法
2010/04/15 Javascript
javascript:json数据的页面绑定示例代码
2014/01/26 Javascript
jQuery获取(选中)单选,复选框,下拉框中的值
2014/02/21 Javascript
JavaScript实现控制打开文件另存为对话框的方法
2015/04/17 Javascript
基于Angularjs实现分页功能
2016/05/30 Javascript
JavaScript对象创建模式实例汇总
2016/10/03 Javascript
vue数据双向绑定的注意点
2017/06/23 Javascript
vue 虚拟dom的patch源码分析
2018/03/01 Javascript
js for终止循环 跳出多层循环
2018/10/04 Javascript
在JavaScript中实现链式调用的实现
2019/12/24 Javascript
vue 监听 Treeselect 选择项的改变操作
2020/08/31 Javascript
[02:07]2018DOTA2亚洲邀请赛主赛事第三日五佳镜头 fy极限反杀
2018/04/06 DOTA
Python 变量类型及命名规则介绍
2013/06/08 Python
利用Python+Java调用Shell脚本时的死锁陷阱详解
2018/01/24 Python
Python实现的求解最大公约数算法示例
2018/05/03 Python
Python JSON格式数据的提取和保存的实现
2019/03/22 Python
Python matplotlib修改默认字体的操作
2020/03/05 Python
Django实现文章详情页面跳转代码实例
2020/09/16 Python
如何用Python进行时间序列分解和预测
2021/03/01 Python
美国生日蛋糕店:Bake Me A Wish!
2017/02/08 全球购物
荣耀俄罗斯官网:HONOR俄罗斯
2020/10/31 全球购物
报到证丢失证明
2014/01/11 职场文书
乡镇消防工作实施方案
2014/03/27 职场文书
软件售后服务承诺书
2014/05/21 职场文书
高中综合实践活动总结
2014/07/07 职场文书
大学生求职自荐信
2015/03/24 职场文书
小学教师师德培训心得体会
2016/01/09 职场文书
公务员的复习计划书,请收下!
2019/07/15 职场文书
python 中[0]*2与0*2的区别说明
2021/05/10 Python
Mysql 设置boolean类型的操作
2021/06/04 MySQL
HashMap实现保存两个key相同的数据
2021/06/30 Java/Android
Win11如何修改dns?Win11修改dns图文教程
2022/01/18 数码科技