python 31 公升級版解決粘包現象

2022-06-27 06:21:12 字數 3864 閱讀 2223

目錄

1.能夠接收來自socket緩衝區的位元組資料;

2.當緩衝區沒有資料可以讀取時,recv會一直處於阻塞狀態,知道緩衝區至少有乙個位元組資料可取,或者客戶端關閉;

3.關閉遠端端並讀取所有資料後,再recv會返回字串。

應用層自定義協議ftp(檔案傳輸協議).

low版:

只能是有限的資料,將總資料長度固定成4個位元組作為報頭,再recv。當檔案資料特別大時,會報錯。

公升級版優點:

1. 自定製報頭。 如:dic =

2. 解決檔案資料過大問題。

把報頭做成字典,字典裡包含將要傳送的真實資料的描述資訊(大小啊之類的),然後json序列化,然後用struck將序列化後的資料長度打包成4個位元組。

我們在網路上傳輸的所有資料 都叫做資料報,資料報裡的所有資料都叫做報文,報文裡面不止有你的資料,還有ip位址、mac位址、埠號等等,其實所有的報文都有報頭,這個報頭是協議規定的。

思路:服務端:

1. 自定義報頭,字典形式,裡面存放檔案資訊等;

2. 然後將報頭字典 ——> json型別字串 ——> 編碼成 bytes型別資料;

3. 將報頭bytes型別的長度(len())——>固定成4個長度的位元組,然後再send();

4. 將報頭bytes型別的內容資料 send();

5. 再傳送總資料,如果資料量特別大時,迴圈讀取、傳送位元組。

客戶端:

1. 先收報頭固定長度,再struct,得到報頭資料的長度;

2. 根據長度接收報頭位元組資料,再解碼,反序列化成字典(json);

3. 從字典獲取檔案、資料的描述資訊(如檔名、大小等),再獲取真實的資料。

# 服務端

import socket

import subprocess

import struct

import json

phone = socket.socket()

phone.bind(('127.0.0.1',8888))

phone.listen(5)

while 1:

conn, addr = phone.accept()

print(f'與客戶端連線')

while 1:

try:

from_client_data = conn.recv(1024)

if from_client_data.upper() == b'q':

print('客戶端已退出!')

break

obj = subprocess.popen(from_client_data.decode("utf-8"),

shell=true,

stdout=subprocess.pipe,

stderr=subprocess.pipe,

)total_data = obj.stdout.read() + obj.stderr.read()

print(len(total_data))

head_dict = # 自定義報頭,字典型別

head_str = json.dumps(head_dict) # 報頭轉換成json的字串型別

head_bytes = head_str.encode('utf-8') # 報頭 轉換成 bytes 型別

head_len_bytes = struct.pack('i', len(head_bytes)) # 固定報頭 位元組數

conn.send(head_len_bytes) # 傳送報頭的 固定位元組

conn.send(head_bytes) # 傳送 報頭資料

conn.send(total_data) # 傳送 總資料, 可迴圈傳送檔案的資料

except connectionreseterror:

print('與客戶端連線中斷!')

break

conn.close()

phone.close()

# 客戶端

import socket

import struct

import json

phone = socket.socket()

phone.connect(('127.0.0.1', 8888))

while 1:

to_server_data = input('>>>').strip().encode('utf-8')

if not to_server_data:

print('內容不能為空!')

continue

phone.send(to_server_data)

if to_server_data.upper() == b'q':

break

head_len_bytes = phone.recv(4) # 接收報頭固定位元組長度

head_int = struct.unpack('i', head_len_bytes)[0] # 報頭長度反解成 int 長度

# print(head_int)

head_bytes = phone.recv(head_int) # 接收int長度的 報頭資料

head_dict = json.loads(head_bytes.decode('utf-8'))

# 將bytes型別的報頭 轉換成原型別(字典)

# print(head_dict['total_size'])

data = b''

while len(data) < head_dict['total_size']: # 小於檔案的大小,迴圈

data = data + phone.recv(1024)

print(len(data))

print(f"")

phone.close()

1. 基於udp協議的socket通訊無需建立管道,先開啟服務端或者客戶端都可以;

2. 基於udp協議的socket通訊,接收、傳送乙個訊息都是無連線的;

3. 只有拿到對方ip位址和埠就可以通訊發訊息,按照順序接收服務端訊息。

# 服務端

import socket

server = socket.socket(socket.af_inet, socket.sock_dgram)

server.bind(('127.0.0.1', 9000))

while 1:

client_data = server.recvfrom(1024)

# print(client_data)

data = client_data[0].decode('utf-8')

print(f'來自客戶端的訊息:')

to_data = input('>>>').encode('utf-8')

server.sendto(to_data, client_data[1])

# 客戶端

import socket

client = socket.socket(socket.af_inet, socket.sock_dgram)

# 基於網路的udp協議的socket

while 1:

to_server_data = input('>>>:').strip()

client.sendto(to_server_data.encode('utf-8'), ('127.0.0.1', 9000))

data, addr = client.recvfrom(1024)

print(f'來自服務端的訊息:')

24點(公升級版)

本24點 可以實現以下操作 查詢4個數經過 和 運算是否可得到nnn 支援僅查詢是否存在和查詢存在的算式 支援多組資料,每組資料結束後請按回車,當n 0 n 0n 0時結束 第一行乙個二進位制數g,0表示不輸出算式,1相反 輸入後過程中不可更改 接下來一行乙個數n nn然後下一行4個數,表示這些數參...

分糖果 5 0公升級版

題目描述 幼兒園裡有n個小朋友,lxhgww老師現在想要給這些小朋友們分配糖果,要求每個小朋友都要分到糖果。但是小朋友們也有嫉妒心,總是會提出一些要求,比如小明不希望小紅分到的糖果比他的多,於是在分配糖果的時候,lxhgww需要滿足小朋友們的k個要求。幼兒園的糖果總是有限的,lxhgww想知道他至少...

7 5 拯救007(公升級版)(30 分)

在老電影 007之生死關頭 live and let die 中有乙個情節,007被毒販抓到乙個鱷魚池中心的小島上,他用了一種極為大膽的方法逃脫 直接踩著池子裡一系列鱷魚的大腦袋跳上岸去!據說當年替身演員被最後一條鱷魚咬住了腳,幸好穿的是特別加厚的靴子才逃過一劫。設鱷魚池是長寬為100公尺的方形,中...