一:什么是socket大數據包發送問題
socket服務器端或者客戶端在向對方發送的數據大於對方接受的緩存時,會出現第二次接受還接到上次命令發送的結果。這就出現象第一次接受結果不全,第二次接果出現第一次結果。
比如send 1900 數據,recv 只接受1024。多於數據900放在緩存區里,第二次命令來的時候,調用send會先把900發回去,在把新數據放到緩存區,等到1024在系統會自動發送過去。
發送數據,一是緩存區滿,二是超時
解決辦法:
在發送數據前,計算發送數據的大小,把大小發給對方。對方接受數據循環,只到接到數據和大小一樣。
二:示例代碼
服務器 # -*- coding:utf-8 -*- __author__ = 'shisanjun' import socket import subprocess server=socket.socket() server.bind(("127.0.0.1",9999)) server.listen(5) while True: conn,addr=server.accept() print("new conn:",addr) while True: print(addr) data=conn.recv(1024) print(len(data)) print(data.decode()) if not data: print("conn close ",addr) break print(data.decode()) cmd_res=subprocess.Popen(data.decode(),shell=True,stdout=subprocess.PIPE) outread=cmd_res.stdout.read() print(outread.decode("gb2312")) conn.send(outread)
客戶端 # -*- coding:utf-8 -*- __author__ = 'shisanjun' import socket client=socket.socket() client.connect(("127.0.0.1",9999)) while True: cmd=input(">>:").strip() if len(cmd)==0:continue print(cmd) client.send(cmd.encode("utf-8")) print("res") res=client.recv(1024) print(res.decode("gb18030"))
大數據發送結果亂問題現象截圖:
三:解決代碼如下:
服務器端 # -*- coding:utf-8 -*- __author__ = 'shisanjun' import socket import subprocess server=socket.socket() server.bind(("127.0.0.1",9999)) server.listen(5) while True: conn,addr=server.accept() print("new conn:",addr) while True: print(addr) data=conn.recv(1024) print(len(data)) print(data.decode()) if not data: print("conn close ",addr) break print(data.decode()) cmd_res=subprocess.Popen(data.decode(),shell=True,stdout=subprocess.PIPE) outread=cmd_res.stdout.read() print(len(outread)) conn.send(("%s" %len(outread)).encode("utf-8")) print(outread.decode("gb2312")) conn.send(outread)
# -*- coding:utf-8 -*- __author__ = 'shisanjun' import socket client=socket.socket() client.connect(("127.0.0.1",9999)) while True: cmd=input(">>:").strip() if len(cmd)==0:continue print(cmd) client.send(cmd.encode("utf-8")) print("res") res_size=client.recv(1024).decode("utf-8") size=0 while size<int(res_size): res=client.recv(1024) print(res.decode("gb18030")) size+=len(res) #這里要用len(),因為最后一次長度不固定