ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-01-24 20:02:11  阅读:158  来源: 互联网

标签:socket 电影 choice header mv 模块 commen 上传 name


1 server_duan.py

 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

 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

 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

 

标签:socket,电影,choice,header,mv,模块,commen,上传,name
来源: https://www.cnblogs.com/tslam/p/15840718.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有