python socket实现文件传输(防粘包)
生活随笔
收集整理的這篇文章主要介紹了
python socket实现文件传输(防粘包)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.文件傳輸的要點:
采用iterator(迭代器對象)迭代讀取,提高讀取以及存取效率;
通過for line in file_handles逐行conn.send();
2.socket粘包問題:
[出現原因]:A.TCP協議為了提高傳輸效率,發送方往往需要收集定量的數據才會封裝給底層并發送,若出現連續send(data),TCP會把該數據進行整合(直到裝滿數據緩沖區),這樣就造成了粘包數據;B.接收方接收方的粘包是由于接收用戶相關進程不及時接收數據,從而導致粘包問題,這是因為接收方先把接收到的數據放在系統接受緩沖區,用戶進程從該緩沖區取定量的數據,但若下一包數據到達前,緩沖區的數據沒有及時的被用戶進程取走,則下一包數據與前一包部分數據在系統緩沖區,就可能導致用戶設定的進程緩沖區從系統緩沖區取走兩個包的部分數據,從而導致粘包
[解決辦法]:A 發送方在send()之前,先向接收方發送數據總量大小,并通過雙端確認,server端發送數據包,然后接收方通過按數據量大小循環設立緩沖區接收數據;;B: TCP提供了PUSH(強制數據立即傳送)操作,但影響性能;C. 周全并且高效的處理粘包請參考:點擊這里
3.code
server.py
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' __author__ = 'kisunny' import socket,os,hashlib server = socket.socket() server.bind(('localhost',6669)) server.listen(2) count = 0 while 1:conn,addr = server.accept()count+=1print('客戶端%s已連接上!' % count)while 1:cmd = conn.recv(1024)order,filename1 = str(cmd.decode()).split()if os.path.isfile(filename1):print('命令:%s\n待發送的文件名:%s' % (order,filename1))#發送文件的大小及文件名post_server = filename1+' '+str(os.stat(filename1).st_size)conn.send(post_server.encode(encoding='utf-8'))#發送文件確認號ACK = conn.recv(1024)#16進制摘要m = hashlib.md5()with open(filename1,'rb') as f:for line in f:m.update(line)conn.send(line)print('%s發送完畢!' % filename1)#此處循環完成之后,繼續send(),可能出現socket粘包conn.send(m.hexdigest().encode())continueelse:ERROR = '錯誤!請檢查文件名!'conn.send(ERROR.encode(encoding='utf-8')) server.close()client.py
__author__ = 'kisunny' import socket,hashlib client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(('localhost',6669)) print('連接服務器成功!') while 1:print('請輸入請求信號及請求內容\n格式:response filename')cmd_order = input('>>:').strip()client.send(cmd_order.encode('utf-8'))cls_msg = client.recv(1024)try:filename2,file_size = str(cls_msg.decode()).split()except ValueError as e:print(e)continueelse:file_len = int(file_size)print('待傳輸文件大小:%s' % file_len)temp = 0client.send('已發送!'.encode(encoding='utf-8'))#MD5對象m_client = hashlib.md5()while temp<file_len:with open('another.txt','wb') as f:#避免服務器連續send出現粘包if temp+1024>file_len:last_len = file_len - tempdata_temp = client.recv(last_len)else:data_temp = client.recv(1024)f.write(data_temp)m_client.update(data_temp)temp += len(data_temp)print('接收文件完畢!\n實際接收文件大小:%s' % temp)#接收16進制摘要md5_info = client.recv(1024)if md5_info.decode() == m_client.hexdigest():print('MD5驗證成功!') client.close() 與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的python socket实现文件传输(防粘包)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python-各种结构解析以及生成器(列
- 下一篇: python中super的用法实例解析