1. 程式人生 > >32、黏包的解決方式、struct模塊

32、黏包的解決方式、struct模塊

大數 總量 接收 多少 rec 能夠 文件的 sendto while

黏包的解決方式

  黏包出現的根本原因是接收方不知道要傳過來多少數據,解決方法1:在傳給接收方以前告訴它要傳過去多少數據。 解決方法2:使用struct方法

解決方法1:傳之前告訴它要傳多少

#服務器端
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(bq)
        break
    conn.send(cmd.encode(
gbk)) num = conn.recv(1024).decode(utf-8) # 2048 conn.send(bok) res = conn.recv(int(num)).decode(gbk) print(res) conn.close() sk.close()
#客戶端
import socket
import subprocess

sk = socket.socket()
sk.connect((127.0.0.1,8080))
while True:
    cmd = sk.recv(1024).decode(gbk)
    
if cmd == q: break res = 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)) #2000 sk.recv(1024) #
ok sk.send(std_out) sk.send(std_err) sk.close()

這種方法的好處:確定了我要接收多大的值

  1)要在文件中配置一個配置項:就是每一次recv的大小

  2)當我們要發送大數據的時候,要明確的告訴接收方要發送多大的數據,以便接收方能夠準確接收所有的數據。

  3)用處:多用在文件傳輸的過程中

    1、大文件的傳輸一定是按照字節讀,每一次讀固定的字節

    2、傳輸的過程中,一邊讀一邊傳,接收端一邊收一邊寫

    3、send這個大文件之前,每一次文件總量減去固定值

    4、recv這個大文件,每一次接收之後減去固定值

這種方法的不好的地方:多了一次交互

  1)send\sendto,在超過一定範圍的時候就會報錯

  2)程序的內存管理(啥意思???

解決方法二:用struct將文件大小或者長度轉化成4個字節的bytes類型

import socket
import subprocess
import struct   #接收命令
sk=socket.socket()
sk.connect((127.0.0.1,8008))
while True:
    cmd=sk.recv(1024).decode(gbk)
    ret=subprocess.Popen(cmd,shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    std_out=ret.stdout.read()
    std_err=ret.stderr.read()
    len_std=len(st_out)+len(std_err)
    len_num=struct.pack(i,len_std)  #將執行命令後的內容長度轉化成4個字節類型
    sk.send(len_num)
    sk.send(std_out)
    sk.send(std_err)

sk.close()
#客戶端
import socket
import struct
sk=socket.socket()
sk.bind((127.0.0.1,8008))
sk.listen()
con,addr=sk.accept()
while True:
    cmd=input(>>>)
    con.send(cmd.encode(gbk))
    num=con.recv(4)
    len_by=struct.unpack(i,num)[0]  #接收到的4個字節長度轉化成數字,重點!!!
    ret=con.recv(len_by).decode(gbk)
    print(ret)
con.close()
sk.close()

32、黏包的解決方式、struct模塊