python——黏包

來源:互聯網
上載者:User

標籤:png   pwd   struct   blank   res   防止   lis   ndt   recv   

 黏包現象

基於tcp先製作一個遠程執行命令的程式(命令ls -l ; lllllll ; pwd)

res=subprocess.Popen(cmd.decode(‘utf-8‘),shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)的結果的編碼是以當前所在的系統為準的,如果是windows,那麼res.stdout.read()讀出的就是GBK編碼的,在接收端需要用GBK解碼且只能從管道裡讀一次結果

同時執行多條命令之後,得到的結果很可能只有一部分,在執行其他命令的時候又接收到之前執行的另外一部分結果,這種顯現就是黏包。

基於tcp協議實現的黏包
import socketimport subprocesssk = socket.socket()sk.connect((‘127.0.0.1‘,8090))while True:    cmd = sk.recv(1024).decode(‘gbk‘)    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.send(std_out.encode(‘utf-8‘))    sk.send(std_err.encode(‘utf-8‘))sk.close()
import socketsk = 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‘))    ret = conn.recv(1024).decode(‘utf-8‘)    print(ret)conn.close()sk.close()
基於udp協議實現的黏包
import socketimport subprocesssk = socket.socket(type=socket.SOCK_DGRAM)addr = (‘127.0.0.1‘,8090)sk.sendto(‘吃了麼‘.encode(‘utf-8‘),addr)while True:    cmd,addr = sk.recvfrom(10000)    ret = subprocess.Popen(cmd.decode(‘gbk‘),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()
import socketsk = socket.socket(type=socket.SOCK_DGRAM)sk.bind((‘127.0.0.1‘,8090))msg,addr = sk.recvfrom(10240)while True:    cmd = input(‘>>>‘)    if cmd == ‘q‘:        break    sk.sendto(cmd.encode(‘utf-8‘),addr)    msg,addr = sk.recvfrom(10240)    print(msg.decode(‘utf-8‘))sk.close()# udp# udp 不會黏包# udp 會丟包

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

基於tcp協議特點的黏包現象成因 

例如基於tcp的通訊端用戶端往服務端上傳檔案,發送時檔案內容是按照一段一段的位元組流發送的,在接收方看了,根本不知道該檔案的位元組流從何處開始,在何處結束

此外,發送方引起的粘包是由TCP協議本身造成的,TCP為提高傳輸效率,發送方往往要收集到足夠多的資料後才發送一個TCP段。若連續幾次需要send的資料都很少,通常TCP會根據最佳化演算法把這些資料合成一個TCP段後一次發送出去,這樣接收方就收到了粘包資料。

UDP不會發生黏包

 

UDP(user datagram protocol,使用者資料包通訊協定)是不需連線的,面向訊息的,提供高效率服務。 不會使用塊的合并最佳化演算法,, 由於UDP支援的是一對多的模式,所以接收端的skbuff(通訊端緩衝區)採用了鏈式結構來記錄每一個到達的UDP包,在每個UDP包中就有了訊息頭(訊息來源地址,連接埠等資訊),這樣,對於接收端來說,就容易進行區分處理了。 即面向訊息的通訊是有訊息保護邊界的。 對於空訊息:tcp是基於資料流的,於是收發的訊息不可為空,這就需要在用戶端和服務端都添加空訊息的處理機制,防止程式卡住,而udp是基於資料報的,即便是你輸入的是空內容(直接斷行符號),也可以被發送,udp協議會幫你封裝上訊息頭髮送過去。 不可靠不黏包的udp協議:udp的recvfrom是阻塞的,一個recvfrom(x)必須對唯一一個sendinto(y),收完了x個位元組的資料就算完成,若是y;x資料就丟失,這意味著udp根本不會粘包,但是會丟資料,不可靠。

 

python——黏包

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.