本文实例讲述了Python实现的FTP通信客户端与服务器端功能。分享给大家供大家参考,具体如下:
一 代码
1、服务端代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
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、客户端代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
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程序设计有所帮助。
原文链接:https://blog.csdn.net/chengqiuming/article/details/78601165