緩衝區,粘包,解決粘包的方法,

2022-06-24 00:51:15 字數 4360 閱讀 9472

緩衝區:暫時存放傳輸資料的,防止你的程式在傳送資料的時候卡主,提高**執行效率

輸入緩衝區:recv

輸出緩衝區:send

緩衝區有長度限制

mtu最大傳輸單元,網路層限制是1500b,每次傳送資料的時候最好不要超過這個數

粘包粘包現象:

1.連續傳送小的資料,間隔時間很短,有可能一次就接受歐到了這幾個連續的情節在一起的小資料,

原因:未來提高tcp傳輸效率,內部提供了乙個叫做nagel演算法,他的意思就是未來避免你連續傳送小資料.

2.當你一次接收的資料長度小於你一次傳送的資料長度,那麼一次接收完剩下的資料會在下一次接收資料的時候一起接收

原因:面向流的傳輸

粘包的根本原因:

兩端互相不知道對方傳送資料的長度

針對上面的原因有兩種解決粘包的方法

1在傳送資料前,先傳送資料的長度,name接收根據的長度來進行接收資料

服務端:

import socket

import subprocess

server = socket.socket()

ip_port = ('192.168.15.113',8001)

server.bind(ip_port)

server.listen()

conn,addr = server.accept()

while 1:

#來自客戶端的指令

print('等待接受資訊。。。')

from_client_cmd = conn.recv(1024).decode('utf-8')

print(from_client_cmd)

sub_obj = subprocess.popen(

from_client_cmd, #客戶端的指令

shell=true,

stdout=subprocess.pipe,

stderr=subprocess.pipe,

)#接受到的返回資訊是bytes型別的,並且windows系統的預設編碼為gbk

server_cmd_msg = sub_obj.stdout.read()

# server_cmd_err = sub_obj.stderr.read().decode('gbk')

cmd_msg_len = str(len(server_cmd_msg))

print('指令返回的正確資訊的長度》',cmd_msg_len)

# print('指令返回的正確資訊》',server_cmd_msg)

# print('指令返回的錯誤資訊...',server_cmd_err)

conn.send(cmd_msg_len.encode('gbk'))

from_client_ack = conn.recv(1024).decode('utf-8')

print('from_client_ack',from_client_ack)

if from_client_ack == 'ok':

conn.send(server_cmd_msg)

else:

continue

客戶端:

import socket

client = socket.socket()

server_ip_port = ('192.168.15.113',8001)

client.connect(server_ip_port)

while 1:

msg = input('請輸入要執行的指令》')

client.send(msg.encode('utf-8'))

#先接收服務端要傳送給我的資訊的長度

from_server_msglen = int(client.recv(1024).decode('gbk'))

print('..........',from_server_msglen)

#給服務端回應乙個收到了你的首席資訊官度的確認資訊

client.send('ok'.encode('utf-8'))

#拿到首席資訊官度後,將首席資訊官度作為引數給了recv,recv就按照這個長度大小來接受服務端後面要給我傳送的資料

from_server_stdout = client.recv(from_server_msglen).decode('gbk')

print('收到的正確資訊:', from_server_stdout)

# from_server_error = client.recv(1024).decode('utf-8')

# print('收到的錯誤資訊:',from_server_error)

2. 把要傳送的資料打成包的形式直接傳輸

服務端:

import socket

import subprocess

import struct

server = socket.socket()

ip_port = ('192.168.15.113',8001)

server.bind(ip_port)

server.listen()

conn,addr = server.accept()

while 1:

#來自客戶端的指令

print('等待接受資訊。。。')

from_client_cmd = conn.recv(1024).decode('utf-8')

print(from_client_cmd)

#通過subprocess模組執行服務端的系統指令,並且拿到指令執行結果

sub_obj = subprocess.popen(

from_client_cmd, #客戶端的指令

shell=true,

stdout=subprocess.pipe, #標準輸出:正確指令的執行結果在這裡

stderr=subprocess.pipe, #標準錯誤輸出:錯誤指令的執行結果在這裡

)#接受到的返回資訊是bytes型別的,並且windows系統的預設編碼為gbk

server_cmd_msg = sub_obj.stdout.read()

# server_cmd_err = sub_obj.stderr.read().decode('gbk')

#首先計算出你將要傳送的資料的長度

cmd_msg_len = len(server_cmd_msg)

#先對資料長度進行打包,打包成4個位元組的資料,目的是為了和你將要傳送的資料拼在一起,就好我們自定製了乙個訊息頭

msg_len_stru = struct.pack('i',cmd_msg_len)

conn.send(msg_len_stru) #首先傳送打包成功後的那4個位元組的資料

conn.sendall(server_cmd_msg) #迴圈send資料,直到資料全部傳送成功

客戶端: 

import socket

import struct

client = socket.socket()

server_ip_port = ('192.168.15.113',8001)

client.connect(server_ip_port)

while 1:

msg = input('請輸入要執行的指令》')

client.send(msg.encode('utf-8'))

#先接收服務端要傳送給我的資訊的長度,前4個位元組,固定的

from_server_msglen = client.recv(4)

unpack_len_msg = struct.unpack('i',from_server_msglen)[0]

#接收資料長度統計,和服務端發給我的資料長度作比較,來確定跳出迴圈的條件

recv_msg_len = 0

#統計拼接接收到的資料,注意:這個不是統計長度

all_msg = b''

while recv_msg_len < unpack_len_msg:

every_recv_data = client.recv(1024)

#將每次接收的資料進行拼接和統計

all_msg += every_recv_data

#對每次接收到的資料的長度進行累加

recv_msg_len += len(every_recv_data)

print(all_msg.decode('gbk'))

解決粘包問題

要知道!所謂粘包問題主要還是因為接收方不知道訊息之間的界限,不知道一次性提取多少位元組的資料所造成的。要解決粘包不外乎乙個條件,就是知道取多少,讓對方事先知道我們要發多少位元組的資料,然後造乙個容器,每次規定的往容器裡面倒水,當水快滿的時候,量出最後一勺還需要多少勺多少的水,最後把這水不多不少的往容...

tcp解決粘包

tcp協議相對於udp協議的差別 tcp udp 是否連線 面向連線 面向非連線 傳輸可靠性 可靠 不可靠 應用場合 少量資料 傳輸大量資料 速度 慢 快 根據這個確定運用場合就好。tcp粘包原因 tcp協議的優化導致而成,也就是在多少毫秒內需要等到多少大小的快取內容,才會進行傳送,在 高併發模式下...

解決粘包現象

簡單版 服務端 usr bin env python coding utf 8 author mr.yang import socket import struct import subprocess phone socket.socket socket.af inet,socket.sock st...