首页 > 代码库 > SELECT版FTP

SELECT版FTP


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

技术分享
 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) == b1:      #防止粘包
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:0
49         }
50         sock.send(json.dumps(data_header).encode())
51         data_header = json.loads(sock.recv(1024).decode())
52         if data_header[ERROR] == 0:
53             file_obj = open(data_header[filename], wb)
54             received_size = 0
55             sock.send(b1)
56             while True:
57 
58                 if received_size == data_header[file_size]:
59                     break
60                 recv_data = http://www.mamicode.com/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端

 



SELECT版FTP