利用socket模块实现 电影的上传与下载(基础版)

1 server_duan.py

利用socket模块实现 电影的上传与下载(基础版)
 1 import socket
 2 from socket import SOL_SOCKET, SO_REUSEADDR
 3 import commen
 4 import os
 5 
 6 
 7 sk = socket.socket()
 8 sk.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
 9 sk.bind(('127.0.0.1', 8081))  # '127.0.0.1':本地回环地址;
10 sk.listen(3)  # 设定"可以等待链接的客户端最大数量"
11 
12 # 服务端下载功能
13 def s_down(c_or_s):
14     # 1 接收电影报头
15     mv_header = commen.recv_header(c_or_s)
16 
17     # 2 接收电影
18     # 2.1 获取电影名和电影大小
19     mv_name = mv_header.get('mv_name')
20     mv_size = mv_header.get('mv_size')
21     # 2.2 接收电影
22     commen.down_file(c_or_s, mv_name, mv_size)
23 
24 # 服务端上传功能
25 def s_up(c_or_s):
26     # 输入/获取电影资源地址(请手动复制地址替换url)
27     source_mv_addr = r'url'
28     mv_list = os.listdir(source_mv_addr)
29     # 发送"电影列表"给客户端
30     commen.send_header(c_or_s, mv_list)  # # 需要sock
31     # 接收客户端选择的电影编号
32     choice_mv_num = commen.recv_header(c_or_s)  # # 需要sock
33     # 校验客户端软件是否发生异常
34     # 正常情况下,客户端发送过来的电影编号都是存在的(客户端已校验过),若不存在说明客户端代码异常
35     if not commen.exist_choice_num(choice_mv_num, mv_list):
36         war_meg = '文件被破坏,请重新下载客户端'
37         print('客户端代码被修改,发送告知: %s' % war_meg)
38         commen.send_header(c_or_s, war_meg)  # # 需要sock
39         return print('等待客户端下载完成后重新链接')
40     # 运行到此步,说明电影编号存在
41     # 上传电影到客户端
42 
43     # 1) 制作电影报头
44     # 获取制作报头需要的信息: 电影名和电影地址
45     mv_name = mv_list[int(choice_mv_num)-1]
46     mv_path = os.path.join(source_mv_addr, mv_name)
47     # 制作
48     mv_header = {'mv_name': mv_name, 'mv_size': os.path.getsize(mv_path)}
49     # print(mv_header)
50     # 2) 发送电影报头
51     commen.send_header(c_or_s, mv_header)  # 需要sock
52     # 3) 发送电影
53     commen.up_file(c_or_s, mv_name, mv_path) # 需要sock
54 
55 
56 # 主程序核心代码
57 def s_src(s_server):
58     func_dict = {'1': s_down, '2': s_up}
59     # 接收客户端的消息,获取客户端的需求: 是上传还是下载,然后做对应处理
60     func_choice = commen.recv_header(s_server)
61     if not func_choice.isdigit():
62         return print('客户端软件损坏')
63     if func_choice not in func_dict:
64         return print('客户端软件损坏')
65     func = func_dict.get(func_choice)
66     # print(func)
67     func(s_server)
68 
69 # 主程序
70 def s_run():
71     while True:
72         sock, addr = sk.accept()
73         while True:
74             try:
75                 s_src(sock)
76             except Exception:
77                 print('客户端异常断开,正在等待其他客户端接入...')
78                 break
79 
80 
81 s_run()
View Code

 

2 client_duan.py

利用socket模块实现 电影的上传与下载(基础版)
 1 import socket
 2 import os
 3 import commen
 4 
 5 client = socket.socket()
 6 client.connect(('127.0.0.1', 8081))
 7 
 8 # 客户端上传功能
 9 def c_up():
10     # 获取本地视频文件地址(这里需手动输入)
11     mv_dir_path = r'E:\BaiduNetdiskDownload\entertainment\video'
12     # 根据地址获取电影列表
13     mv_list = os.listdir(mv_dir_path)
14     # 展示电影条目
15     print('电影清单>>>:')
16     for i, j in enumerate(mv_list):
17         print(i + 1, j)
18     while True:
19         # 1 选择要上传的电影编号
20         choice_num = input('请输入想要上传的电影编号>>>:').strip()
21         # 2 判断电影编号是否存在,不存在,重新输入
22         if not commen.exist_choice_num(choice_num, mv_list):
23             continue
24         # 运行到此步说明电影编号存在
25         # 3 发送电影
26 
27         # 3.1 制作报头
28         # 3.11 获取报头必要信息
29         # 获取电影名字
30         mv_name = mv_list[int(choice_num) - 1]
31         # 获取电影地址
32         mv_path = os.path.join(mv_dir_path, mv_name)
33         # 启发: 两行代码一般没必要定义成函数
34         # 3.12 制作
35         mv_header = {'mv_name': mv_name, 'mv_size': os.path.getsize(mv_path)}
36         # 3.2 发送报头
37         commen.send_header(client, mv_header)
38         # 3.3 发送电影
39         commen.up_file(client, mv_name, mv_path)
40         break
41 
42 # 客户端下载功能
43 def c_down():
44     # 接收客户端发来的电影列表信息
45     mv_list = commen.recv_header(client)
46     # 将电影以"枚举"方式展示给客户端
47     for i, j in enumerate(mv_list):
48         print(i + 1, j)
49     # 选择要下载的电影编号,以及后续下载相关
50     while True:
51         # 1 输入想要下载的电影编号
52         choice_num = input('请输入想要下载的电影编号>>>:').strip()
53         # 2 判断电影编号是否存在,若不存在,则重新输入电影编号
54         if not commen.exist_choice_num(choice_num, mv_list):
55             continue
56         # 3 输入的电影编号存在, 将电影编号发送给服务端
57         commen.send_header(client, choice_num)
58 
59         # 4 接收服务端的电影数据
60         # 1)接收电影报头
61         mv_header = commen.recv_header(client)
62         # 2)接收电影
63         mv_name = mv_header.get('mv_name')
64         mv_size = mv_header.get('mv_size')
65         commen.down_file(client, mv_name, mv_size)
66         break
67 
68 # 主程序
69 def c_run():
70     func_dict = {'1': c_up, '2': c_down}  # 注意函数名后无小括号,否则检查语法阶段就直接执行函数了
71     while True:
72         func_choice = input("请选择想要的功能:\r\n"
73                             "1: 上传电影\r\n"
74                             "2: 下载电影\r\n>>>:"
75                             ).strip()
76 
77         if not func_choice.isdigit():
78             print('输入不合法')
79             continue
80         if func_choice not in func_dict:
81             print('无该功能')
82             continue
83         func = func_dict.get(func_choice)
84         print(func)
85         # print('======')
86         # 将客户端选择的功能编号发送给服务端
87         commen.send_header(client, func_choice)
88         func()
89 
90 
91 c_run()
View Code

 

3 commen.py

利用socket模块实现 电影的上传与下载(基础版)
 1 import json
 2 import struct
 3 
 4 # 发送报头,其实就是发送了某一种数据类型的数据(如一个字典)
 5 # 所以,当你想发送一个字典或列表等任意非文件的数据,都可以用如下函数发送.一步到位.
 6 def send_header(c_or_s, header):
 7     json_str_bt = json.dumps(header)
 8     # 打包报头
 9     pack_bt = struct.pack('i', len(json_str_bt))
10     # 发送打包的报头
11     c_or_s.send(pack_bt)
12     # 发送报头
13     c_or_s.send(json_str_bt.encode('utf-8'))
14 
15 def up_file(c_or_s, file_name, file_path):
16     with open(file_path, 'rb') as f:
17         for line in f:
18             c_or_s.send(line)
19     print('>>>:"%s"上传完了' % file_name)
20 
21 def recv_header(c_or_s):
22     # 接收打包的报头
23     pack_bt = c_or_s.recv(4)
24     # 解压报头
25     bt_size = struct.unpack('i', pack_bt)[0]
26     # 接收报头
27     bytes_bt = c_or_s.recv(bt_size)
28     # print(type(bytes_bt), bytes_bt.decode('utf-8'))
29     # 将报头转换成原数据类型
30     orig_header = json.loads(bytes_bt)
31     return orig_header
32 
33 def down_file(c_or_s, file_name, file_size):
34     with open(file_name, 'wb') as f:
35         recv_size = 0
36         while recv_size < file_size:
37             tmp_data = c_or_s.recv(1024)
38             recv_size += len(tmp_data)
39             f.write(tmp_data)
40     print('>>>:"%s"下载完了' % file_name)
41 
42 def exist_choice_num(choice_num, mv_list):
43     if not choice_num.isdigit():
44         print('输入无效!')
45         return False
46     choice_num = int(choice_num)
47     if choice_num not in range(1, len(mv_list) + 1):
48         print('您输入的编号不存在!')
49         return False
50     return True
View Code

 

上一篇:nginx 代理wss协议


下一篇:Go跨域头