日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python学习day32 黏包 struct模块

發(fā)布時間:2023/12/10 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python学习day32 黏包 struct模块 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

為什么會出現(xiàn)黏包問題??

首先只有在TCP協(xié)議中才會出現(xiàn)黏包現(xiàn)象

是因為TCP協(xié)議是面向流的協(xié)議

在發(fā)送的數(shù)據(jù) 傳輸過程中 有緩存機(jī)制 來避免數(shù)據(jù)丟失

因此 在連續(xù)發(fā)送小數(shù)據(jù)的時候 以及接收大小不符的時候都容易出現(xiàn)黏包現(xiàn)象

本質(zhì)還是因為我們在接受數(shù)據(jù)的時候不知道發(fā)送的數(shù)據(jù)的長短

怎么解決黏包問題?

在接收端發(fā)送要發(fā)送的數(shù)據(jù)的大小

一種是不帶struct??一種是帶struct? 定制協(xié)議

?

黏包

http://www.cnblogs.com/Eva-J/articles/8244551.html#_label5

?注意:只有TCP有粘包現(xiàn)象,UDP永遠(yuǎn)不會粘包

黏包成因:

多個send可能會發(fā)生黏包現(xiàn)象

優(yōu)化算法不優(yōu)化

發(fā)生黏包兩種現(xiàn)象:

情況一 發(fā)送方的緩存機(jī)制

發(fā)送端需要等緩沖區(qū)滿才發(fā)送出去,造成粘包(發(fā)送數(shù)據(jù)時間間隔很短,數(shù)據(jù)了很小,會合到一起,產(chǎn)生粘包)

情況二 接收方的緩存機(jī)制

接收方不及時接收緩沖區(qū)的包,造成多個包接收(客戶端發(fā)送了一段數(shù)據(jù),服務(wù)端只收了一小部分,服務(wù)端下次再收的時候還是從緩沖區(qū)拿上次遺留的數(shù)據(jù),產(chǎn)生粘包)

?

?如何解決黏包?

存在的問題: 多了一次交互。程序的運(yùn)行速度遠(yuǎn)快于網(wǎng)絡(luò)傳輸速度,所以在發(fā)送一段字節(jié)前,先用send去發(fā)送該字節(jié)流長度,這種方式會放大網(wǎng)絡(luò)延遲帶來的性能損耗

struct模塊

該模塊可以把一個類型,如數(shù)字,轉(zhuǎn)成固定長度的bytes

這個模塊可以把要發(fā)送的數(shù)據(jù)長度轉(zhuǎn)換成固定長度的字節(jié)。這樣客戶端每次接收消息之前只要先接受這個固定長度字節(jié)的內(nèi)容看一看接下來要接收的信息大小,那么最終接受的數(shù)據(jù)只要達(dá)到這個值就停止,就能剛好不多不少的接收完整的數(shù)據(jù)了。

?

import structret = struct.pack('i', 2049) # pack方法,將對象轉(zhuǎn)換成固定字節(jié)長度bytes類型 num = struct.unpack('i', ret) # 解包 print(num) # 元組 print(num[0]) # 數(shù)字

?

?

連續(xù)send? 連續(xù)receive

?

我們在網(wǎng)絡(luò)上傳輸?shù)乃袛?shù)據(jù),都叫數(shù)據(jù)包

數(shù)據(jù)包中的數(shù)據(jù),都叫報文

報文里不只有你的數(shù)據(jù) ip地址 mac地址 端口號

所有的報文都有報頭? 相當(dāng)于協(xié)議 接收多少字節(jié) 什么順序 等等

報頭可以自己定制

根據(jù)報頭來解包接收的數(shù)據(jù)

  復(fù)雜的應(yīng)用上就會用到定制報頭

    比如:傳輸文件的時候

      文件名、大小、類型、路徑

?

網(wǎng)絡(luò)傳輸中,處處有有協(xié)議,協(xié)議就是一堆報文和報頭 ———字節(jié)

協(xié)議的解析過程我們不需要關(guān)心

我們也可以自定制協(xié)議

?

?實現(xiàn)一個大文件的上傳或下載:

客戶端作發(fā)送端:

import socket import os import json import structsk = socket.socket() sk.connect(('127.0.0.1',8090))# 發(fā)文件 # 定制報頭 head = {'filepath':r'H:\python\day32','filename':r'05 python fullstack s9day32 strcuct模塊定制報頭的理論.mp4','filesize':None} file_path = os.path.join(head['filepath'],head['filename']) file_size = os.path.getsize(filepath) head['filesize'] = file_sizejson_head = json.dumps(head) # 字典轉(zhuǎn)成字符串 bytes_head = json_head.encode('utf-8') # 字符串轉(zhuǎn)bytes類型 head_len = len(bytes_head) # 報頭的長度 pack_len = struct.pack('i', head_len) # 報頭長度轉(zhuǎn)成固定的4字節(jié)長度 sk.send(pack_len) # 先發(fā)報頭長度 sk.send(bytes_head) # 再發(fā)報頭內(nèi)容 # 然后再發(fā)文件內(nèi)容: buffer = 1024 with open(filepath, 'rb') as f:while file_size:if file_size >= buffer:content = f.read(buffer)sk.send(content)file_size -= bufferelse:content = f.read(file_size)sk.send(content)break sk.close

服務(wù)端:

import socket import os import json import structsk = socket.socket() sk.bind(('127.0.0.1',8090)) sk.listen()conn, addr = sk.accept() # 接收 head_len = conn.recv(4) # 接收報頭長度 head_len = struct.unpack('i', head_len)[0] # 解包成元組 第一個 json_head = conn.recv(head_len).decode('utf-8') head = json.loads(json_head) # 報頭 filesize = head['filesize'] buffer = 1024 # 寫入文件 with open(head['filename'], 'wb') as f:while filesize:if filesize >= buffer:content = conn.recv(buffer)f.write(content)filesize -= bufferelse:f.write(conn.recv(filesize))breakconn.close sk.close

?

轉(zhuǎn)載于:https://www.cnblogs.com/happyfan/p/10450905.html

總結(jié)

以上是生活随笔為你收集整理的python学习day32 黏包 struct模块的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。