day_socketserver模块实现多个客户端的上传下载

用socket实现之后就试着用一下socketserver模块

 

 1 import socketserver
 2 import json
 3 import struct
 4 import os
 5 import hashlib
 6 class Myserver(socketserver.BaseRequestHandler):
 7     def handle(self) -> None:
 8         self.options_list={'download':self.download,'upload':self.upload}
 9         self.conn = self.request
10         self.login()
11         self.opt_dic = self.my_recv()
12         if self.opt_dic['operate'] in self.options_list:
13             self.options_list[self.opt_dic['operate']]()
14 
15 
16     def get_md5(self,username, password):
17         md5 = hashlib.md5(username.encode('utf-8'))
18         md5.update(password.encode('utf-8'))
19         return md5.hexdigest()
20 
21     def my_recv(self):
22         leng = self.conn.recv(4)
23         msg_dic = self.conn.recv(struct.unpack('i', leng)[0]).decode('utf-8')
24         msg = json.loads(msg_dic)
25         return msg
26 
27 
28     def my_send(self,dic):
29         str_dic = json.dumps(dic)
30         length = struct.pack('i', len(str_dic))
31         self.conn.send(length)
32         self.conn.send(str_dic.encode('utf-8'))
33 
34 
35     def upload(self):
36         msg = self.my_recv()
37         with open(msg['filename'], mode='wb') as f:
38             while msg['filesize'] > 0:
39                 content = self.conn.recv(1024)
40                 msg['filesize'] -= len(content)  # 防止接收信息不够,由于tcp的优化,发送方发送1024个字节,接收时可能会分为几块,每一块多大,这里总长度就减去多少
41                 f.write(content)
42 
43 
44     def download(self):
45         abs_path = r'/home/lmh/PycharmProjects/网络编程/tmp'
46         filename = os.path.basename(abs_path)
47         filesize = os.path.getsize(abs_path)
48         dic = {'filename': filename, 'filesize': filesize}
49         self.my_send(dic)
50         with open(abs_path, mode='rb') as f:
51             while filesize > 0:
52                 content = f.read(1024)
53                 filesize -= len(content)
54                 self.conn.send(content)
55 
56 
57     def login(self):
58         flag = True
59         while flag:
60             msg = self.my_recv()
61             with open(r'/home/lmh/PycharmProjects/网络编程/socketserver模块/userinfo', 'r', encoding='utf-8') as f:
62                 for line in f:
63                     name, pwd = line.strip().split('|')
64                     if name == msg['username'] and pwd == self.get_md5(name, msg['password']):
65                         res = True
66                         flag = False
67                         break
68                 else:
69                     res = False
70                 dic = {'operate': 'login', 'result': res}
71                 self.my_send(dic)
72 
73 server = socketserver.ThreadingTCPServer(('127.0.0.1',9001),Myserver)
74 server.serve_forever() #固定的写法
View Code

 

 

 1 import socket
 2 import os
 3 import sys
 4 import struct#处理黏包
 5 import json
 6 sk = socket.socket()
 7 sk.connect(('127.0.0.1',9001))
 8 
 9 def upload(sk):
10     opt_dic = {'operate':'upload'}
11     my_send(sk,opt_dic)
12     #文件名/文件大小
13     abs_path = r'/home/lmh/PycharmProjects/网络编程/tmp'
14     filename = os.path.basename(abs_path)
15     filesize = os.path.getsize(abs_path)
16     dic = {'filename':filename,'filesize':filesize}
17     my_send(sk,dic)
18     with open(abs_path,mode='rb') as f:
19         while filesize>0:
20             content = f.read(1024)
21             filesize-=len(content)
22             sk.send(content)
23     sk.close()
24 
25 
26 def download(sk):
27     opt_dic = {'operate':'download'}
28     my_send(sk,opt_dic)
29     msg=my_recv(sk)
30     with open(msg['filename'], mode='wb') as f:
31         while msg['filesize'] > 0:
32             content = sk.recv(1024)
33             msg['filesize'] -= len(content)  # 防止接收信息不够,由于tcp的优化,发送方发送1024个字节,接收时可能会分为几块,每一块多大,这里总长度就减去多少
34             f.write(content)
35     # sk.close()
36 
37 
38 def my_send(sk,dic):
39     str_dic = json.dumps(dic)
40     b_dic = str_dic.encode('utf-8')
41     length = struct.pack('i', len(b_dic))
42     sk.send(length)
43     sk.send(b_dic)
44 
45 
46 def my_recv(sk):
47     length = sk.recv(4)
48     msg = sk.recv(struct.unpack('i', length)[0]).decode('utf-8')
49     msg = json.loads(msg)
50     return msg
51 
52 
53 '''
54 登录
55 '''
56 def login(sk):
57     flag = True
58     while flag:
59         username = input('用户名:').strip()
60         password = input('密 码:').strip()
61         dic = {'username': username, 'password': password}
62         my_send(sk,dic)
63         msg = my_recv(sk)
64         if msg['result']:
65             print('登录成功')
66             flag=False
67         else:
68             print('登录失败')
69 
70 
71 login(sk)
72 # 上传和下载的逻辑
73 opt_lst=['upload','download']
74 for index,opt in enumerate(opt_lst,1):
75     print(index,opt)
76 
77 num = int(input('请选择你要操作的序号:'))
78 if hasattr(sys.modules[__name__],opt_lst[num-1]):
79     getattr(sys.modules[__name__],opt_lst[num-1])(sk)
80 
81 
82 sk.close()
View Code

 

在实现的过程中,server端的函数反射遇到了问题,由于之前都是用的classmethod,这次写反射的过程中由于对对象和类的区分不深刻,总是错误,最后还是用字典去实现反射。

```python
对象是类的实例,类是对象的模板。对象是通过new classname产生的,用来调用类的方法;类的构造方法
```

```python
classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。如果定义的方法里传了self,在调用的时候也要传self
```

```python
静态变量 是个所有对象共享的变量 由对象/类调用,但不能重新赋值
绑定方法 自带self参数的函数,由对象调用
类方法 是个自带cls参数的函数 由对象/类调用
```

```python
class A(object):

# 属性默认为类属性(可以给直接被类本身调用)
num = "类属性"

# 实例化方法(必须实例化类之后才能被调用)
def func1(self): # self : 表示实例化类后的地址id
print("func1")
print(self)

# 类方法(不需要实例化类就可以被类本身调用)
@classmethod
def func2(cls): # cls : 表示没用被实例化的类本身
print("func2")
print(cls)
print(cls.num)
cls().func1()

# 不传递传递默认self参数的方法(该方法也是可以直接被类调用的,但是这样做不标准)
def func3():
print("func3")
print(A.num) # 属性是可以直接用类本身调用的

# A.func1() 这样调用是会报错:因为func1()调用时需要默认传递实例化类后的地址id参数,如果不实例化类是无法调用的
A.func2()
A.func3()
```

posted @ 2020-07-10 11:17  哎呀you  阅读(101)  评论(0)    收藏  举报