最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python粘包的解決方案

 更新時(shí)間:2024年01月21日 10:34:33   作者:Az_plus  
粘包就是在數(shù)據(jù)傳輸過程中有多個(gè)數(shù)據(jù)包被粘連在一起被發(fā)送或接受,本文主要介紹了python粘包的解決方案,具有一定的參考價(jià)值,感興趣的可以了解一下

什么是粘包

粘包就是在數(shù)據(jù)傳輸過程中有多個(gè)數(shù)據(jù)包被粘連在一起被發(fā)送或接受

服務(wù)端:

import socket
import struct

# 創(chuàng)建Socket
Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 綁定服務(wù)器和端口號(hào)
servers_addr = ('127.0.0.1', 8081)
Socket.bind(servers_addr)

# 監(jiān)聽客戶端請(qǐng)求 最大連接數(shù)為5
Socket.listen(5)
print('服務(wù)器啟動(dòng)成功,等待客戶端連接...')

# 接受數(shù)據(jù)
client_socket, client_addr = Socket.accept()
print('與客戶端建立連接', client_addr)
client_socket.setblocking(False)
# 數(shù)據(jù)交換
while True:
    data = client_socket.recv(10880)  # 最大1024字節(jié)
    if len(data) < 1:
        print('關(guān)閉服務(wù)')
        break

    # 接受客戶器端傳來的數(shù)據(jù)
    print(data.decode())

    # 向客戶端返回?cái)?shù)據(jù)
    client_socket.sendall(data)
    break
Socket.close()

客戶端:

import socket
import subprocess

# 獲取cmd指令
cmd_from_client = 'ipconfig'
cmd_msg = subprocess.Popen(cmd_from_client,
                           shell=True,  # 使用shell命令
                           stdout=subprocess.PIPE,  # 管道一:輸出結(jié)果
                           stderr=subprocess.PIPE  # 管道二:輸出錯(cuò)誤信息
                           )
msg_one = cmd_msg.stdout.read().decode('gbk')
msg_two = cmd_msg.stderr.read().decode('gbk')
msg = msg_one + msg_two


# 創(chuàng)建Socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 服務(wù)器地址和端口
server_address = ('localhost', 8081)

# 連接服務(wù)器
client_socket.connect(server_address)
print('已連接到服務(wù)器:', server_address)

while True:
    # 發(fā)送數(shù)據(jù)
    # message = input('>>>>')
    client_socket.sendall(msg.encode())

    # 接收響應(yīng)
    response = client_socket.recv(1024)
    print('服務(wù)器響應(yīng):', response.decode())
    break
client_socket.close()

案例中使用了subprocess模塊輸出了ip信息,在服務(wù)端打印的數(shù)據(jù)中可以看到內(nèi)容是能夠正常輸出的

image-20240120212503635

但是根據(jù)客戶端的控制臺(tái)顯示數(shù)據(jù)在返回時(shí)被截?cái)嗔?/p>

其實(shí)原因很簡(jiǎn)單:

response = client_socket.recv(1024)

數(shù)據(jù)在服務(wù)端中能一次性的接收,但由于客戶端只能接受1024,所以就不會(huì)從緩存中一下取完大于1024的那部分?jǐn)?shù)據(jù),其實(shí)不管是客戶端還是服務(wù)端,recv()的緩存區(qū)大小都是可控的,但是發(fā)送方發(fā)送了一個(gè) 10KB 的數(shù)據(jù)包,而接收方使用 recv(1024) 只能一次接收最多 1KB 的數(shù)據(jù),這樣就需要多次調(diào)用 recv() 來接收完整的數(shù)據(jù),可能會(huì)引發(fā)粘包問題

客戶端
import socket

# 創(chuàng)建 Socket 對(duì)象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 服務(wù)器地址和端口
server_address = ('localhost', 8081)

# 連接服務(wù)器
client_socket.connect(server_address)
print('已連接到服務(wù)器:', server_address)

# 發(fā)送數(shù)據(jù)包
message1 = 'Hello'
message2 = 'World'

# 連續(xù)發(fā)送兩個(gè)數(shù)據(jù)包
client_socket.sendall(message1.encode())
client_socket.sendall(message2.encode())

# 關(guān)閉連接
client_socket.close()
服務(wù)端
import socket

# 創(chuàng)建 Socket 對(duì)象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 綁定服務(wù)器地址和端口
server_address = ('localhost', 8081)
server_socket.bind(server_address)

# 監(jiān)聽客戶端請(qǐng)求
server_socket.listen(1)
print('等待客戶端連接...')

while True:
    # 接受連接
    client_socket, client_addr = server_socket.accept()
    print('與客戶端建立連接:', client_addr)

    # 接收數(shù)據(jù)
    data = client_socket.recv(1024)  # 接收數(shù)據(jù)包
    received_data = data.decode()

    # 處理接收到的數(shù)據(jù)
    print('接收到數(shù)據(jù):', received_data)

理想情況:

等待客戶端連接...
與客戶端建立連接: ('127.0.0.1', 61127)
接收到數(shù)據(jù): Hello
接收到數(shù)據(jù): World

實(shí)際情況:

等待客戶端連接...
與客戶端建立連接: ('127.0.0.1', 61127)
接收到數(shù)據(jù): HelloWorld

導(dǎo)致粘包的原因

1.緩沖區(qū)大小限制:在TCP傳輸中,由于數(shù)據(jù)過大,超出緩存區(qū)大小限制,導(dǎo)致接收方不能接收到所有的數(shù)據(jù)包,造成了數(shù)據(jù)包的截?cái)嗷騺G失

2.底層協(xié)議特性:底層傳輸協(xié)議如 TCP 是面向流的,不保留消息邊界。TCP 協(xié)議會(huì)將數(shù)據(jù)流切分為適當(dāng)大小的數(shù)據(jù)塊進(jìn)行傳輸,因此無法保證每個(gè)數(shù)據(jù)包的邊界

3.數(shù)據(jù)發(fā)送速度過快:發(fā)送方連續(xù)發(fā)送數(shù)據(jù)包,而接收方無法及時(shí)處理,導(dǎo)致多個(gè)數(shù)據(jù)包在接收緩沖區(qū)中堆積

解決方案:struct模塊

利用pack()方法將任意長(zhǎng)度的 數(shù)字 打包成新的數(shù)據(jù)

再用unpack()方法將固定長(zhǎng)度的 數(shù)字 解包成打包前數(shù)據(jù)真實(shí)的長(zhǎng)度

  • pack()方法 第一個(gè)參數(shù)是格式,第二個(gè)參數(shù)是整數(shù)(數(shù)據(jù)的長(zhǎng)度),返回值是一個(gè)新的數(shù)據(jù)
  • unpack()方法 第一個(gè)參數(shù)是格式,第二個(gè)參數(shù)是 pack()方法打包后生成的新數(shù)據(jù),返回值是一個(gè)元組,元組中放著打包前數(shù)據(jù)真實(shí)的長(zhǎng)度
import struct

msg_one = '你好'
msg_two = ('struct 是 Python 標(biāo)準(zhǔn)庫中的一個(gè)模塊,用于進(jìn)行字節(jié)與數(shù)據(jù)類型之間的相互轉(zhuǎn)換。它提供了'
           '一組函數(shù)來打包(pack)和解包(unpack)數(shù)據(jù),使得數(shù)據(jù)在網(wǎng)絡(luò)傳輸或文件存儲(chǔ)時(shí)能夠以二進(jìn)制形式進(jìn)行處理。')
total = len(msg_one) + len(msg_two)  # 106

# 將數(shù)據(jù)打包
res = struct.pack('i', total)

# 解包數(shù)據(jù)
un_res = struct.unpack('i', res)

print(len(res))  # 4
print(res)  # bytes類型:  b'j\x00\x00\x00'
print(un_res)  # 元組類型: (106,)

粘包問題的根源在于,接收端不知道發(fā)送端將要傳送的字節(jié)流的長(zhǎng)度,所以解決粘包的方法就是圍繞,如何讓發(fā)送端在發(fā)送數(shù)據(jù)前,把自己將要發(fā)送的字節(jié)流總大小讓接收端知曉,然后接收端來一個(gè)死循環(huán)接收完所有數(shù)據(jù)

客戶端
import socket
import struct

# 創(chuàng)建 Socket 對(duì)象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 服務(wù)器地址和端口
server_address = ('localhost', 8081)

# 連接服務(wù)器
client_socket.connect(server_address)
print('已連接到服務(wù)器:', server_address)

# 發(fā)送數(shù)據(jù)包
msg = b'helloworld'
data = struct.pack('i', len(msg))


# 先發(fā)送報(bào)頭
client_socket.send(data)

# 發(fā)送真實(shí)數(shù)據(jù)
client_socket.send(msg)
服務(wù)端
import socket
import struct

# 創(chuàng)建 Socket 對(duì)象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 綁定服務(wù)器地址和端口
server_address = ('localhost', 8081)
server_socket.bind(server_address)

# 監(jiān)聽客戶端請(qǐng)求
server_socket.listen(1)
print('等待客戶端連接...')

while True:
    # 接受連接
    client_socket, client_addr = server_socket.accept()
    print('與客戶端建立連接:', client_addr)

    # 接收數(shù)據(jù)
    data = client_socket.recv(1024)  # 接收數(shù)據(jù)包
    received_data = struct.unpack('i', data)
    data_len = received_data[0]

    real_data = client_socket.recv(data_len)

    # 處理接收到的數(shù)據(jù)
    print('接收到數(shù)據(jù):', real_data.decode('utf8'))

根據(jù)該原理改進(jìn)案例代碼

客戶端
import socket
import struct

# 創(chuàng)建Socket
Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 綁定服務(wù)器和端口號(hào)
servers_addr = ('127.0.0.1', 8082)
Socket.bind(servers_addr)

# 監(jiān)聽客戶端請(qǐng)求 最大連接數(shù)為5
Socket.listen(5)
print('服務(wù)器啟動(dòng)成功,等待客戶端連接...')

# 接受數(shù)據(jù)
client_socket, client_addr = Socket.accept()
print('與客戶端建立連接', client_addr)
# client_socket.setblocking(False)
# 數(shù)據(jù)交換
while True:
    # 接受報(bào)頭
    header = client_socket.recv(4)  # 最大1024字節(jié)
    if len(header) < 1:
        print('關(guān)閉服務(wù)')
        break
    data_len = struct.unpack('i', header)[0]
    print(data_len)

    # 接受真實(shí)數(shù)據(jù)
    real_data = client_socket.recv(data_len)
    print(real_data.decode('gbk'))

    # 向客戶端返回?cái)?shù)據(jù)
    client_socket.send(real_data)
服務(wù)端
import socket
import struct
import subprocess

# 獲取cmd指令
cmd_from_client = 'ipconfig'
cmd_msg = subprocess.Popen(cmd_from_client,
                           shell=True,  # 使用shell命令
                           stdout=subprocess.PIPE,  # 管道一:輸出結(jié)果
                           stderr=subprocess.PIPE  # 管道二:輸出錯(cuò)誤信息
                           )
msg_one = cmd_msg.stdout.read().decode('gbk')
msg_two = cmd_msg.stderr.read().decode('gbk')
msg = msg_one + msg_two

# 創(chuàng)建Socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 服務(wù)器地址和端口
server_address = ('localhost', 8082)

# 連接服務(wù)器
client_socket.connect(server_address)
print('已連接到服務(wù)器:', server_address)

while True:
    # 先發(fā)報(bào)頭
    data_len = struct.pack('i', len(msg))
    client_socket.send(data_len)

    # 發(fā)送數(shù)據(jù)
    client_socket.send(msg.encode('gbk'))

    # 接收響應(yīng)
    response = client_socket.recv(data_len[0])
    print('服務(wù)器響應(yīng):', response.decode('gbk'))

到此這篇關(guān)于python粘包的解決方案的文章就介紹到這了,更多相關(guān)python 粘包內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python機(jī)器學(xué)習(xí)之KNN近鄰算法

    Python機(jī)器學(xué)習(xí)之KNN近鄰算法

    KNN可以說是最簡(jiǎn)單的分類算法之一,同時(shí),它也是最常用的分類算法,文中非常詳細(xì)的介紹了該算法,對(duì)正在學(xué)習(xí)python的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-05-05
  • 使用Python批量處理Excel文件并轉(zhuǎn)為csv文件示例

    使用Python批量處理Excel文件并轉(zhuǎn)為csv文件示例

    這篇文章主要介紹了使用Python批量處理Excel文件并轉(zhuǎn)為csv文件示例,文中通過代碼示例給大家介紹非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-12-12
  • Python最常用的20 個(gè)包總結(jié)

    Python最常用的20 個(gè)包總結(jié)

    這篇文章主要介紹了Python最常用的20 個(gè)包總結(jié),在平時(shí)使用Python的過程中,需要用到很多有用的包,今天就來盤點(diǎn)一下常用的包,需要的朋友可以參考下
    2023-04-04
  • 詳細(xì)介紹Ruby中的正則表達(dá)式

    詳細(xì)介紹Ruby中的正則表達(dá)式

    這篇文章主要介紹了詳細(xì)介紹Ruby中的正則表達(dá)式,文章中還給出了用于搜索和替換的正則表達(dá)式的使用實(shí)例,需要的朋友可以參考下
    2015-04-04
  • django中SMTP發(fā)送郵件配置詳解

    django中SMTP發(fā)送郵件配置詳解

    這篇文章主要介紹了django中SMTP發(fā)送郵件配置,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • python向圖片里添加文字

    python向圖片里添加文字

    這篇文章主要為大家詳細(xì)介紹了python向圖片里添加文字,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • 在Linux系統(tǒng)上安裝Python的Scrapy框架的教程

    在Linux系統(tǒng)上安裝Python的Scrapy框架的教程

    這篇文章主要介紹了在Linux系統(tǒng)上安裝Python的Scrapy框架的教程,Scrapy是著名的專門針對(duì)搜索引擎的爬蟲制作而研發(fā)的Python框架,需要的朋友可以參考下
    2015-06-06
  • Python字典簡(jiǎn)介以及用法詳解

    Python字典簡(jiǎn)介以及用法詳解

    字典(dictionary)是除列表意外python之中最靈活的內(nèi)置數(shù)據(jù)結(jié)構(gòu)類型。列表是有序的對(duì)象結(jié)合,字典是無序的對(duì)象集合。兩者之間的區(qū)別在于:字典當(dāng)中的元素是通過鍵來存取的,而不是通過偏移存取。
    2016-11-11
  • Python提取PDF發(fā)票信息保存Excel文件并制作EXE程序的全過程

    Python提取PDF發(fā)票信息保存Excel文件并制作EXE程序的全過程

    之前零散的用過一點(diǎn)python做數(shù)據(jù)處理,這次又遇到一個(gè)數(shù)據(jù)處理的小功能,下面這篇文章主要給大家介紹了關(guān)于Python提取PDF發(fā)票信息保存Excel文件并制作EXE程序的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • 解決python爬蟲中有中文的url問題

    解決python爬蟲中有中文的url問題

    今天小編就為大家分享一篇解決python爬蟲中有中文的url問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05

最新評(píng)論

磐石市| 龙井市| 贵州省| 麟游县| 朝阳市| 顺昌县| 灵台县| 仪陇县| 勐海县| 呈贡县| 玛曲县| 建阳市| 柏乡县| 格尔木市| 石棉县| 雅安市| 南汇区| 鄂温| 沙坪坝区| 长乐市| 海原县| 炎陵县| 建湖县| 焉耆| 泰和县| 化德县| 揭西县| 蓝山县| 沙坪坝区| 穆棱市| 江永县| 连州市| 叙永县| 辽中县| 余江县| 大方县| 屯留县| 三都| 陆川县| 定陶县| 浦东新区|