粘包問題
描述:接收到傳來的資料過大時,會殘留資料,下次軟體會在作業系統拿到上次遺留的資料就為粘包問題
tcp協議的nagle演算法會將資料量較小,並且傳送時間間隔較短的多個資料合在一起發
解決辦法
自定義報頭
服務端from socket import * #優化**
import subprocess
import struct #pack將整型的數字轉換成固定長度的bytes型別 unpick則相反
import json
server=socket(af_inet,sock_stream) #建立服務端物件,用tcp
server.bind(('127.0.0.1',8080)) #繫結埠
server.listen(5) #半連線池同時請求數
while true:
conn,client_addr=server.accept() #建立與客戶端鏈結
print('新的客戶端',client_addr)
while true:
try:
cmd=conn.recv(1024) #cmd=b'dir'為bytes型別
if len(cmd) == 0:break #出現客戶端斷開時解決方案
# 執行系統命令
obj=subprocess.popen(cmd.decode('utf-8'),#要為字串型別
shell=true,
stderr=subprocess.pipe,#錯誤結果
stdout=subprocess.pipe#正確結果
)stdout=obj.stdout.read()#得到的結果為bytes,windows執行為gbk
stderr=obj.stderr.read()
#先製作報頭
header_dic=
header_json=json.dumps(header_dic) #得到的結果為字串型別
header_bytes=header_json.encode('utf-8')#轉換為bytes傳送
#1、先把報頭的長度len(header_bytes)打包成4個bytes,然後傳送
conn.send(struct.pack('i',len(header_bytes))) #報頭長度固定,用i格式
#2、傳送報頭
conn.send(header_bytes)
#3、再傳送真實的資料
conn.send(stdout)
conn.send(stderr)
except connectionreseterror:
break
conn.close()
客戶端from socket import *
import struct
import json
client=socket(af_inet,sock_stream)
client.connect(('127.0.0.1',8080))
while true:
cmd=input('>>: ').strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8'))
#1、先收4個位元組,該4個位元組中包含報頭的長度
header_len=struct.unpack('i',client.recv(4))[0] #uupack的結果為只有乙個值的元組,取第乙個值,為傳來資料的bytes長度。
# 將收到bytes型別解析成元組
#2、再接收報頭
header_bytes=client.recv(header_len) #收到序列化的bytes資料
#從報頭中解析出想要的內容
header_json=header_bytes.decode('utf-8')#將bytes型別轉換成字串
header_dic=json.loads(header_json) #反序列化出訪問的字典
print(header_dic)
total_size=header_dic['total_size'] #拿到服務端發過來真實的資料bytes的總長度
#3、再收真實的資料
recv_size=0 #定義變數,接受位元組長度的初始值
res=b'' #接收到的資料初始值
while recv_size < total_size : #小於所有的資料長度繼續迴圈
data=client.recv(1024) #1024變成更大跟快取有關,且不合理,最大為8096
res+=data
recv_size+=len(data) #date為實際接收到的資料
print(res.decode('gbk')) #通過解碼列印資料
struct 模組的運用
import struct
import json
header_dic=
header_json=json.dumps(header_dic)
header_bytes=header_json.encode('utf-8') #把str型別轉成bytes型別
obj=struct.pack('i',len(header_bytes)) #固定報頭長度
print(obj,len(obj))
## res=struct.unpack('i',header)
# print(res[0])#讀出的為元組,第乙個值為報頭長度
TCP的套接字
摘自 深入理解計算機網路 王達著 機械工業出版社 1.ipv4資料報頭部格式 2.ipv6資料報頭部格式 3.ipv4資料報的封裝與解封裝 4.ipv4資料報的分段與重組 5.arp協議報文格式及arp表 6.arp位址解析原理 7.icmp協議及報文格式 8.ipv6協議族的其它協議 9.tcp的...
TCP套接字程式設計
網路程式設計又稱為套接字程式設計,為了與遠端計算機進行資料傳輸,需要連線到網際網路,而程式設計中的 套接字 就是用來連線該網路的工具。它本身具有連線的含義,還可以表示為兩台計算機之間的網路連線。4.呼叫accept函式受理連線請求 基於tcp的服務端 客戶端 tcp伺服器端預設函式呼叫順序 sock...
TCP套接字程式設計
對於socket不理解的可以檢視 c語言通過socket程式設計實現tcp通訊,linux socket程式設計 socket詳解 先看看程式效果圖 提示如果伺服器,直接通過ctrl z關閉,這樣程式占用的位址不會釋放,需要以下操作 1.ps 檢視程序 2.kill 9 程式pid 強制殺死程序 服...