1. 程式人生 > >python筆記(解決TCP黏包問題)

python筆記(解決TCP黏包問題)

@幾個重要的協議:tcp,udp,ip,arp
@應用層的協議:http(https),ftp,smtp(郵件相關的協議)
解決黏包問題
一、為什麼會出現黏包現象?
(1)首先只有在TCP協議中才會出現黏包現象。
(2)是因為CP協議是面向流的協議。
(3)在傳送的資料傳輸的過程中還有快取機制來避免資料丟失。
(4)並因此在連續傳送小資料的時候以及接收大小不符的時候都容易出現黏包現象。
(5)本質還是因為我們在接收資料的時候不知道傳送的資料的長短。
(6)解決新包問題並在傳輸大量資料之前先告訴接收端要傳送的資料大小。

1、黏報現象:資料已經亂了,沒接收完,接收多了
UDP:不會黏包,但丟包
在這裡插入圖片描述


TCP:會黏包,但不丟包(優化演算法)

解決黏包問題:
好處:確定了我到底要接收多大的資料
1、要在檔案中配置一個配置項:就是每一次recy的大小 buffer=4096
2、當我們要傳送大資料的時候,要明確的告訴接收方要傳送多大的資料,以便接收方能夠準確的接收到所有資料
3、 多用在檔案傳輸的過程中
(1)大檔案的傳輸一定是按照字讀每一次讀固定的位元組
(2)傳輸的過程中一邊讀一邊傳接收端一邊收一邊寫

一、struct模組

import struct
ret = struct.pack('i',4096)  #'i'代表int,就是把一個數字轉換成固定長度的bytes型別(4個位元組)
print(ret,len(ret))

num = struct.unpack('i',ret)
print(num[0])

輸出結果:

b’\x00\x10\x00\x00’ 4
4096

在這裡插入圖片描述
二、解決例子(在server端下發命令在client端接收命令)
TCP---->server:

import struct
import socket

sk = socket.socket()
sk.bind(('127.0.0.1',8090))
sk.listen(5)
conn,addr = sk.accept()
while True:
    cmd = input('>>')
    if cmd == 'q':
        conn.send(b'q')
        break
    conn.send(cmd.encode('gbk'))
    num = conn.recv(4) #4
    num = struct.unpack('i',num)[0]
    res = conn.recv(int(num)).decode('gbk')
    print(res)
conn.close()
sk.close()

TCP---->client:

import struct
import socket
import subprocess

sk = socket.socket()
sk.connect(('127.0.0.1',8090))

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()
    len_num = len(std_out) + len(std_err)
    num_by = struct.pack('i',len_num)
    sk.send(num_by)
    sk.send(std_out)
    sk.send(std_err)
sk.close()