ftp(网络传输)--BaseRequesHandler(tcp协议下的多个客户端连接)--urandom(随机生成字节字符串)--hmac(类似于hashlib)
ftp(网络传输,下载)简单实例:
server服务端:
# server 服务端 import json import socket import struct server = socket.socket() server.bind(("127.0.0.1",8001)) server.listen() conn,addr = server.accept() #接收文件的描述信息长度 struct_data_len = conn.recv(4) data_len=struct.unpack("i",struct_data_len)[0] print("字典的字节长度为:",data_len) #设置勺子大小,把字典字节给取出来 file_info_bytes =server.recv(data_len) #拿到字典的json格式 file_info_json = file_info_bytes.decode("utf-8") #还原回字典 file_info_dict = json.loads(file_info_json) print("字典的内容:",file_info_dict) #根据发来的文件信息,准备循环接收. recv_sum = 0 #设置文件的打开和存储路径,with open,会用到 file_path = "D:\s18\jj"+"\\"+file_info_dict["file_name"] #开始真正接收 with open(file_path,"wb") as f: #循环结束的条件是,写进去的文件长度比对方给你的文件长度相等就结束. while recv_sum<file_info_dict["file_size"]: every_recv_data = conn.recv(1024) recv_sum += len(every_recv_data) f.write(every_recv_data)
client 客户端:
import os import socket import json import struct client = socket.socket() client.connect(('127.0.0.1',8001)) #统计文件大小 file_size = os.path.getsize(r'D:\python_workspace_s18\day029\aaa.mp4') #统计文件描述信息,给服务端,服务端按照我的文件描述信息来保存文件,命名文件等等,现在放到一个字典里面了 file_info = { 'file_name':'aaa.mp4', 'file_size':file_size, } #由于字典无法直接转换成bytes类型的数据,所以需要json来将字典转换为json字符串.在把字符串转换为字节类型的数据进行发送 #json.dumps是将字典转换为json字符串的方法 file_info_json = json.dumps(file_info) #将字符串转换成bytes类型的数据 file_info_byte = file_info_json.encode('utf-8') #为了防止黏包现象,将文件描述信息的长度打包后和文件的描述信息的数据一起发送过去 data_len = len(file_info_byte) #把字典的字节长度封包成4个字节.方便对方接收后面的字典消息 data_len_struct = struct.pack('i',data_len) #把字典的字节长度和字典的字节一起发送过去,对方先接受的是字典的长度,然后此消息,改变下次接收的字节流大小,就能拿到字典内容,
#而自己,不需要担心,对方把字典信息和我发送的文件内容相混. client.send(data_len_struct + file_info_byte) #定义一个变量,=0,作为每次读取文件的长度的累计值 sum = 0 #打开的aaa.mp4文件,rb的形式, with open('aaa.mp4','rb') as f: #循环读取文件内容 while sum < file_size: #每次读取的文件内容,每次读取1024B大小的数据 every_read_data = f.read(1024) #将sum累加,统计长度 sum += len(every_read_data) #将每次读取的文件的真实数据返送给服务端 client.send(every_read_data)
二、关于socketserver.BaseRequestHandler
以下代码是固定写法,可以让你的TCP服务端,跟多人同时通话
import socketserver class MyServer(socketserver.BaseRequestHandler): # MyServer类名不固定,但是必须要继承socketserver.BaseRequestHandler def handle(self): # handle方法名固定写法 # self.request conn while 1: from_client_data = self.request.recv(1024) print(from_client_data.decode('utf-8')) to_client_data = input('>>>').strip().encode('utf-8') self.request.send(to_client_data) if __name__ == '__main__': ip_port = ('127.0.0.1', 8888) socketserver.TCPServer.allow_reuse_address = True server = socketserver.ThreadingTCPServer(ip_port,MyServer) # 固定写法((ip地址,端口),MyServer) # 源码显示:上一行代码: 创建socket对象,绑定ip地址和端口,监听 server.serve_forever()
该地址与此相关,有时间再仔细研究:
https://www.cnblogs.com/progor/p/8617042.html
1 import socketserver #1、引入模块 2 class MyServer(socketserver.BaseRequestHandler): #2、自己写一个类,类名自己随便定义,然后继承socketserver这个模块里面的BaseRequestHandler这个类 3 4 def handle(self): #3、写一个handle方法,必须叫这个名字 5 #self.request #6、self.request 相当于一个conn 6 7 self.request.recv(1024) #7、收消息 8 msg = '亲,学会了吗' 9 self.request.send(bytes(msg,encoding='utf-8')) #8、发消息 10 11 self.request.close() #9、关闭连接 12 13 # 拿到了我们对每个客户端的管道,那么我们自己在这个方法里面的就写我们接收消息发送消息的逻辑就可以了 14 pass 15 if __name__ == '__mian__': 16 #thread 线程,现在只需要简单理解线程,别着急,后面很快就会讲到啦,看下面的图 17 server = socketserver.ThreadingTCPServer(('127.0.0.1',8090),MyServer)#4、使用socketserver的ThreadingTCPServer这个类,将IP和端口的元祖传进去,还需要将上面咱们自己定义的类传进去,得到一个对象,相当于我们通过它进行了bind、listen 18 server.serve_forever() #5、使用我们上面这个类的对象来执行serve_forever()方法,他的作用就是说,我的服务一直开启着,就像京东一样,不能关闭网站,对吧,并且serve_forever()帮我们进行了accept 19 20 21 #注意: 22 #有socketserver 那么有socketclient的吗? 23 #当然不会有,我要作为客户去访问京东的时候,京东帮我也客户端了吗,客户端是不是在我们自己的电脑啊,并且socketserver对客户端没有太高的要求,只需要自己写一些socket就行了。
三、os.urandom(n)
随机生成n个字节字符串的方法
四. hmac模块
def hmac_md5(key, s): return hmac.new(key.encode('utf-8'), s.encode('utf-8'), 'MD5').hexdigest() class User(object): def __init__(self, username, password): self.username = username self.key = ''.join([chr(random.randint(48, 122)) for i in range(20)]) self.password = hmac_md5(self.key, password)