粘包现象
粘包现象的成因:
tcp协议的特点,面向流的,为了传输可靠传输,所以有很多优化机制。
无边界 所有在连接建立的基础上传递的数据之间没有界限
收发消息很有可能不完全相等
缓存机制,导致没发过去的消息会在发送端缓存
没有接收完的消息会在接收端缓存
解决:
给应用层定制协议
先发送一个定长的可以表示待发送数据长度的bytes 先接收一个固定长度
在发送要发送的数据 在按照长度接收数据
方案二:
先发送一个定长表示待发送字典长度的bytes (先接收一个固定长度)
再发送要发送字典(再按照长度接收字典)
在发送文件 (再根据字典中的信息接收相应的内容)
####大文件传输实例
实例一:
import os import json import struct import socket # sk = socket.socket() sk.bind(('192.168.11.36',9000)) sk.listen() conn,addr = sk.accept() print(addr) dic = {'filename':' D:\战狼.rmvb', 'filesize':os.path.getsize(r' D:\战狼.rmvb)} str_dic = json.dumps(dic).encode('utf-8') dic_len = struct.pack('i',len(str_dic)) conn.send(dic_len) conn.send(str_dic) with open(r' D:\战狼.rmvb','rb') as f: # content = f.read() while True: content = f.read(1024) if not content:break conn.send(content) # if not conn.send(content):break conn.close() sk.close()
import json import struct import socket sk = socket.socket() sk.connect(('192.168.11.36',9000)) dic_len = sk.recv(4) dic_len = struct.unpack('i',dic_len)[0] str_dic = sk.recv(dic_len).decode('utf-8') dic = json.loads(str_dic) with open(dic['filename'],'wb') as f: while True: content = sk.recv(dic['filesize']) if not content:break f.write(content) sk.close()
示例二:
###加入MD5验证
#########server 端 import os import json import struct import socket import hashlib md5 = hashlib.md5() with open(r'D:\战狼.rmvb', 'rb') as f: while True: b = f.read(1024) if not b: break md5.update(b) md5 = md5.hexdigest() print(md5) sk = socket.socket() sk.bind(('127.0.0.1',9000)) sk.listen() conn,addr = sk.accept() print(addr) dic = {'filename':'黏包.mp4', 'filename_md5':str(md5), 'filesize':os.path.getsize(r'D:\战狼.rmvb')} str_dic = json.dumps(dic).encode('gbk') dic_len = struct.pack('i', len(str_dic)) conn.send(dic_len) conn.send(str_dic) with open(r'D:\战狼.rmvb', 'rb') as f: content = f.read() conn.send(content) conn.close() sk.close()
#####客户端 import json import struct import socket import hashlib sk = socket.socket() sk.connect(('127.0.0.1',9000)) dic_len = sk.recv(4) dic_len = struct.unpack('i',dic_len)[0] str_dic = sk.recv(dic_len).decode('gbk') dic = json.loads(str_dic) md5 = hashlib.md5() with open(dic['filename'],'wb') as f: while True: content = sk.recv(1024) f.write(content) if not content:break md5.update(content) md5 = md5.hexdigest() print(md5) if dic['filename_md5'] == str(md5): print('md5校验正确--下载成功') else: print('文件验证失败') sk.close()
socket 验证客户端的合法性
#server端
#秘钥 # hashlib # md5 # hashlib.md5('秘钥') import os import socket import hmac secret_key = '老衲洗头用飘柔'.encode('utf-8') # 秘钥 sk = socket.socket() sk.bind(('127.0.0.1',9000)) sk.listen() while True: try: conn,addr = sk.accept() random_bytes = os.urandom(32) # 加密方法 conn.send(random_bytes) obj = hmac.new(key =secret_key,msg =random_bytes) ret = obj.hexdigest() msg = conn.recv(1024).decode('utf-8') if msg == ret:print('是合法的客户端') else:conn.close() finally: sk.close() break
##客户端 import socket import hmac secret_key = '老衲洗头用飘柔'.encode('utf-8') sk = socket.socket() sk.connect(('127.0.0.1',9000)) urandom = sk.recv(1024) hmac_obj = hmac.new(key = secret_key,msg =urandom) sk.send(hmac_obj.hexdigest().encode('utf-8')) sk.close()