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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python学习day32 黏包 struct模块

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

為什么會出現黏包問題??

首先只有在TCP協議中才會出現黏包現象

是因為TCP協議是面向流的協議

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

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

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

怎么解決黏包問題?

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

一種是不帶struct??一種是帶struct? 定制協議

?

黏包

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

?注意:只有TCP有粘包現象,UDP永遠不會粘包

黏包成因:

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

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

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

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

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

情況二 接收方的緩存機制

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

?

?如何解決黏包?

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

struct模塊

該模塊可以把一個類型,如數字,轉成固定長度的bytes

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

?

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

?

?

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

?

我們在網絡上傳輸的所有數據,都叫數據包

數據包中的數據,都叫報文

報文里不只有你的數據 ip地址 mac地址 端口號

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

報頭可以自己定制

根據報頭來解包接收的數據

  復雜的應用上就會用到定制報頭

    比如:傳輸文件的時候

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

?

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

協議的解析過程我們不需要關心

我們也可以自定制協議

?

?實現一個大文件的上傳或下載:

客戶端作發(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) # 字典轉成字符串 bytes_head = json_head.encode('utf-8') # 字符串轉bytes類型 head_len = len(bytes_head) # 報頭的長度 pack_len = struct.pack('i', head_len) # 報頭長度轉成固定的4字節(jié)長度 sk.send(pack_len) # 先發(fā)報頭長度 sk.send(bytes_head) # 再發(fā)報頭內容 # 然后再發(fā)文件內容: 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

服務端:

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

?

轉載于:https://www.cnblogs.com/happyfan/p/10450905.html

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。