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

歡迎訪問 生活随笔!

生活随笔

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

python

python网络编程2-黏包问题

發布時間:2025/3/15 python 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python网络编程2-黏包问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、復習

# ip地址:一臺機器在網絡上的位置 # 公網ip 私網ip # TCP協議:可靠,面向連接的,耗時長#三次握手#四次揮手 # UDP協議:不可靠,無連接,效率高 # ARP協議:通過ip找mac的過程 # ip協議屬于網絡osi中的網絡層 # TCP協議和UDP協議屬于傳輸層 # arp協議屬于數據鏈路層

二、黏包(第一條和第二條數據合并發送)

tcp:不會丟包會黏包

udp:會丟包不會黏包

tcp黏包案例:

server_tcp端:

#server端 import socket sk=socket.socket() sk.bind(('127.0.0.1',8090)) sk.listen()conn,addr=sk.accept() while True:cmd=input('>>>')conn.send(cmd.encode('utf-8'))ret1=conn.recv(1024).decode('utf-8')ret2 = conn.recv(1024).decode('utf-8')print(ret1)print(ret2)conn.close() sk.close()

client_tcp端:

#client端 import socket import subprocess sk=socket.socket()sk.connect(('127.0.0.1',8090)) while True:cmd=sk.recv(1024).decode('utf-8')ret=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)std_out='stdout:'+(ret.stdout.read()).decode('gbk')std_err='stderr:'+(ret.stderr.read()).decode('gbk')sk.send(std_out.encode('utf-8'))sk.send(std_err.encode('utf-8')) sk.close()

運行結果:

udp丟包案例:(udp起server和client)

server_udp端:

import socket sk = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1',8090) sk.bind(ip_port) msg, addr = sk.recvfrom(10240) while True:cmd = input('>>>')if cmd == 'q':breaksk.sendto(cmd.encode('utf-8'),addr)msg1,addr = sk.recvfrom(20480)print(msg1.decode('utf-8'))msg2, addr = sk.recvfrom(20480)print(msg2.decode('utf-8')) sk.close()

client_udp端:

import socket import subprocess sk = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1',8090) sk.sendto(b'hi',ip_port) while True:cmd,addr = sk.recvfrom(1024)cmd = cmd.decode('utf-8')ret = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)std_out = 'stdout:'+(ret.stdout.read()).decode('gbk')std_err = 'stderr:'+(ret.stderr.read()).decode('gbk')print(std_out)print(std_err)sk.sendto(std_out.encode('utf-8'),addr)sk.sendto(std_err.encode('utf-8'),addr) sk.close() #不會黏包,會丟包

運行結果:

運行結果顯示,如果udp的接收數據量大小滿足發送數據量大小,那么就不會丟包,若是不滿足發送數據量大小,則就會報錯。而不是丟包

三 、黏包的觸發

情況一:發送方的緩存機制:發送端要等緩沖區滿才發送出去。造成黏包(發送數據時間間隔很短,數據很小,會合并一起造成粘包)

如:

#server端 import socket sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() conn,addr=sk.accept() ret=conn.recv(12) ret2=conn.recv(12) print(ret) print(ret2) conn.close() sk.close()#關閉時會發空消息 # 多個send小的數據連在一起,可能會發生黏包現象,是tcp內部的優化算法引起的 #client端 import socket sk=socket.socket() sk.connect(('127.0.0.1',8080)) sk.send(b'hello') import time # time.sleep(0.01) sk.send(b'world') sk.send(b'dd') sk.close()

運行結果:(有時會黏包有時不會)

情況二:接收方的緩沖機制

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

如:

# server端 import socket sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen()conn,addr=sk.accept() ret=conn.recv(2) ret2=conn.recv(10) print(ret) print(ret2) conn.close() sk.close()# 黏包的本職問題:不知道發送數據的長度 # 連續的小數據包會被合并 # client端 import socket sk=socket.socket() sk.connect(('127.0.0.1',8080))sk.send(b'hello,egg') sk.close()

運行結果:

總結

黏包現象只發生在tcp協議中:

1.從表面上看,黏包問題主要是因為發送方和接收方的緩存機制、tcp協議面向流通信的特點。

2.實際上,主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少字節的數據所造成的

四、黏包的解決方案

解決方案一:

問題的根源在于,接收端不知道發送端將要傳送的字節流的長度,所以解決粘包的方法就是圍繞,如何讓發送端在發送數據前,把自己將要發送的字節流總大小讓接收端知曉,然后接收端來一個死循環接收完所有數據。

# server # server 下發命令 給client import socket sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() conn,addr=sk.accept() while True:cmd=input(">>>")if cmd=='q':conn.send(b'q')breakconn.send(cmd.encode('gbk'))num=conn.recv(1024).decode('utf-8')conn.send(b'ok')res=conn.recv(int(num)).decode('gbk')print(res) conn.close() sk.close() # client # 接收server端的命令后在自己的機器上執行 import socket import subprocesssk=socket.socket() sk.connect(('127.0.0.1',8080)) while True:cmd=sk.recv(1024).decode('gbk')if cmd=='q':breakres=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)std_out=res.stdout.read()std_err=res.stderr.read()sk.send(str((len(std_out)+len(std_err))).encode('utf-8'))sk.recv(1024) #oksk.send(std_out)sk.send(std_err) sk.close()# 好處:確定我到底要接收多大的數據 # recv的大小一般不超過4096 # 要在文件中配置一個配置項:就是每次recv的大小 buffer=4096 # 當我們發送大數據量的時候,要明確的告訴接收方要發送多大數據以便接收方能準確接收到所有數據 # 多用在文件傳輸過程中#大文件的傳輸一定是按照字節讀 每次讀固定的字節# 傳輸的過程中 一邊讀一邊傳 接收端:一邊收一邊寫# send大文件之前,告知大小。大小-4096-4096....-->0 文件傳輸完# recv大文件,先接受大小。再recv2048.不會丟 大小-2048-2048 -->0 文件接收完 # 不好的地方:多了一次交互 # 5個g數據 # send 和sendto在超過一定范圍后,都會報錯

運行結果:

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

解決方案進階

剛剛的方法,問題在于我們我們在發送

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

struct模塊

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

>>> struct.pack('i',1111111111111)struct.error: 'i' format requires -2147483648 <= number <= 2147483647 #這個是范圍

# server 下發命令 給client import socket import struct sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() conn,addr=sk.accept() while True:cmd=input(">>>")if cmd=='q':conn.send(b'q')breakconn.send(cmd.encode('gbk'))num=conn.recv(4) #4 2048num = struct.unpack('i', num)[0]res=conn.recv(int(num)).decode('gbk') #2048print(res) conn.close() sk.close() # 連續send兩個小數據 # 兩個recv,第一個recv特別小 # 遠程執行命令的程序:ipconfig--> 2000,只接收1024.就會緩存,下次繼續接收上次未接收完的數據#連續send兩個小數據2+8=10 # 2 # 8 #兩個recv,第一個recv特別小 # recv(數據的長度) # 接收server端的命令后在自己的機器上執行 import socket import subprocess import structsk=socket.socket() sk.connect(('127.0.0.1',8080)) while True:cmd=sk.recv(1024).decode('gbk')if cmd=='q':breakres=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)std_out=res.stdout.read()std_err=res.stderr.read()len_num=len(std_out)+len(std_err)num_by=struct.pack('i',len_num)sk.send(num_by) # 4 2048sk.send(std_out) # 1024sk.send(std_err) #1024 sk.close()

運行結果:

五、ftp發送視頻

sever:

import socket import struct import json buffer=1024 # ip地址和端口號需要寫在配置文件中 sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen()conn,addr=sk.accept() # 接收 head_len=conn.recv(4) # 報頭長度 head_len=struct.unpack('i',head_len)[0] head_json=conn.recv(head_len).decode('utf-8') head=json.loads(head_json) filesize=head['filesize'] with open(head['filename'],'wb') as f:while filesize:print(filesize)if filesize>=buffer:content=conn.recv(buffer)f.write(content)filesize-=bufferelse:content=conn.recv(filesize)f.write(content)filesize=0break f.close() conn.close() sk.close() #發送端 import socket import os import json import struct sk=socket.socket() sk.connect(('127.0.0.1',8080)) # 發送文件 buffer=2046 # 改成4096文件大小會變:發送和接收時間不匹配 # 讀操作快,寫速度慢。緩沖數據多head={'filepath':r'E:\test','filename': '[反貪風暴3]BD國語.mp4','filesize':None} file_path=os.path.join(head['filepath'],head['filename']) filesize=os.path.getsize(file_path) head['filesize']=filesize json_head=json.dumps(head) #字典轉成了字符串 byte_head=json_head.encode('utf-8') # 字符串轉成了bytes head_len=len(byte_head) # 報頭的長度 pack_len=struct.pack('i',head_len) sk.send(pack_len) # 先發報頭的長度 sk.send(byte_head) # 再發送bytes類型的報頭 with open(file_path,'rb') as f:while filesize:print(filesize)if filesize>=buffer:content=f.read(buffer) # 每次讀取出來的大小sk.send(content)filesize-=bufferelse:content=f.read(filesize)sk.send(content)filesize=0break f.close() sk.close()

參考自https://www.cnblogs.com/Eva-J/articles/8244551.html#_label5

?

?

?

總結

以上是生活随笔為你收集整理的python网络编程2-黏包问题的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产野外作爱视频播放 | 黄瓜视频成人 | 高清国产mv在线观看 | 毛利兰被扒开腿做同人漫画 | 成人依依网 | 91精品人妻一区二区三区蜜桃欧美 | 久久久久国产综合av天堂 | 国产 中文 字幕 日韩 在线 | 各处沟厕大尺度偷拍女厕嘘嘘 | 一本一道波多野结衣一区二区 | 欧美 日韩 中文字幕 | 国产a一级 | 日本女人一区二区三区 | 91伦理 | 国产永久免费无遮挡 | 中国免费观看的视频 | 日本在线精品 | 青娱乐极品在线 | 超能一家人电影免费喜剧在线观看 | 欧美视频在线一区 | 99精品国产成人一区二区 | 女女av在线 | 奇米狠狠干 | 少妇性l交大片免潘金莲 | 日韩一区2区 | 国产精品久久午夜夜伦鲁鲁 | 国产一区二区三区播放 | 巨乳女教师的诱惑 | 日韩精品一区二区亚洲av | 日韩在线一卡 | 91久| 91精品国产欧美一区二区成人 | 久久影视精品 | 台湾一级视频 | 夜夜骑天天干 | 五月婷婷激情小说 | 欧美色悠悠| 国产91精品一区 | 亚洲女成人图区 | 日韩一区欧美 | 免费观看日批视频 | 日p免费视频 | 蜜臀网在线 | 性视频网址| 丰满人妻一区二区三区免费视频棣 | 91涩漫成人官网入口 | 国产精品www. | 狠狠躁日日躁 | 深夜影院在线观看 | 日本精品一区二区三区在线观看 | 久久免费黄色 | 婷婷色综合 | 91av久久久 | 毛片一区 | 亚洲男人第一网站 | 精品一区二区三区在线观看 | 国产资源网站 | 8mav在线| 男人视频网站 | 又黄又爽的视频在线观看 | 亚洲永久免费 | 91超薄丝袜肉丝一区二区 | 色播久久 | 日韩三级黄色片 | 日日噜噜夜夜狠狠久久波多野 | 男生草女生的视频 | 九月婷婷丁香 | 色综合色综合网色综合 | 国产福利不卡 | 国产精品国产一区 | 日日爽夜夜爽 | 少妇自摸视频 | 亚洲福利视频一区二区 | 国产亚洲欧美精品久久久久久 | 天天做天天躁天天躁 | 欧美10p| 天天色天天色 | 中文字幕av无码一区二区三区 | 国产污污网站 | 亚洲精品国产精品乱码不99 | 日韩毛片基地 | 毛片全黄| 国产综合久久久久久鬼色 | 亚洲AV午夜成人片 | 亚洲欧美日韩电影 | 蝌蚪自拍网站 | 国产精品ww | 欧美日韩视频一区二区 | 国产婷婷色综合av蜜臀av | 一级黄色a| 午夜激情综合网 | 国产麻豆一区二区三区在线观看 | 秋霞午夜伦理 | 91亚洲精华国产精华精华液 | 午夜xxx| 天堂网www在线| 精品一区二区三区在线视频 | 国产人成精品 | 女人下面无遮挡 |