簡單版
服務端
#!/usr/bin/env python
#_*_ coding:utf-8 _*_
#author:mr.yang
import
socket
import
struct
import
subprocess
phone =socket.socket(socket.af_inet,socket.sock_stream)
phone.bind((
'127.0.0.1
',8080))
phone.listen(5)
print('
setting...')
while true: #
鏈結迴圈
conn,a =phone.accept()
while true: #
通訊迴圈
try:
#1.接收資料
data = conn.recv(8096)
print('
客戶端資料:
',data)
#2.執行命令,拿到結果
obj = subprocess.popen(data.decode('
utf-8
'), shell=true, #
shell 可以解析前面的字串,相當於cmd
stdout=subprocess.pipe, #
正確管道
stderr=subprocess.pipe) #
錯誤管道
stdout = obj.stdout.read() #
bytes型別
stderr =obj.stderr.read()
#3.將結果返回給客戶端
#第一步: 制定固定長度的報頭
total_size = len(stdout) +len(stderr)
header = struct.pack('i'
,total_size)
#第二步: 把報頭髮送給客戶端
conn.send(header)
#第三步: 在傳送真實的資料
conn.send(stdout)
conn.send(stderr)
#分開寫的原因,tcp會自動粘包,可以起到優化的作用
except
connectionreseterror:
break
conn.close
phone.close()
客戶端
#!/usr/bin/env python
#_*_ coding:utf-8 _*_
#author:mr.yang
'''recv不能設定數值特別大的原因:
1.在接收檔案的時候可能超過指定數值
2.自己的作業系統的快取不能無限大,最大也不能超過作業系統的快取
'''import
socket,struct
phone =socket.socket(socket.af_inet,socket.sock_stream)
phone.connect((
'127.0.0.1
',8080))
while
true:
#1.發命令
cmd = input('
>>:
').strip()
ifnot cmd:continue
phone.send(cmd.encode(
'utf-8'))
#2.拿到命令結果
#第一步: 先收報頭
header = phone.recv(4)
#第二步: 從報頭中解析出對真實資料的描述資訊 (資料的長度)
tolal_size = struct.unpack('i'
,header)[0]
#第三步: 接收真實的資料
recv_size=0
recv_data=b''
while recv_size res = phone.recv(100)
recv_data +=res
recv_size +=len(res)
print(recv_data.decode('
gbk'
))phone.close()
終極版
服務端
#!/usr/bin/env python
#_*_ coding:utf-8 _*_
#author:mr.yang
import
socket
import
struct
import
json
import
subprocess
'''相對於簡單版的優化
1.報頭資訊少
2.struct的i格式有限制
'''phone =socket.socket(socket.af_inet,socket.sock_stream)
phone.bind((
'127.0.0.1
',8080))
phone.listen(5)
print('
setting...')
while true: #
鏈結迴圈
conn,a =phone.accept()
while true: #
通訊迴圈
try:
#1.接收資料
data = conn.recv(8096)
print('
客戶端資料:
',data)
#2.執行命令,拿到結果
obj = subprocess.popen(data.decode('
utf-8
'), shell=true, #
shell 可以解析前面的字串,相當於cmd
stdout=subprocess.pipe, #
正確管道
stderr=subprocess.pipe) #
錯誤管道
stdout = obj.stdout.read() #
bytes型別
stderr =obj.stderr.read()
#3.將結果返回給客戶端
#第一步: 制定固定長度的報頭
header_dic=
header_json=json.dumps(header_dic)
header_bytes = header_json.encode('
utf-8')
#第二步:先發報頭的長度
conn.send(struct.pack('i'
,len(header_bytes)))
#第三步:再發報頭
conn.send(header_bytes)
#第四步: 在傳送真實的資料
conn.send(stdout)
conn.send(stderr)
#分開寫的原因,tcp會自動粘包
except
connectionreseterror:
break
conn.close
phone.close()
客戶端
#!/usr/bin/env python
#_*_ coding:utf-8 _*_
#author:mr.yang
'''recv不能設定數值特別大的原因:
1.在接收檔案的時候可能超過指定數值
2.自己的作業系統的快取不能無限大,最大也不能超過作業系統的快取
'''import
socket
import
struct
import
json
phone =socket.socket(socket.af_inet,socket.sock_stream)
phone.connect((
'127.0.0.1
',8080))
while
true:
#1.發命令
cmd = input('
>>:
').strip()
ifnot cmd:continue
phone.send(cmd.encode(
'utf-8'))
#2.拿到命令結果
#第一步: 先收報頭的長度
obj = phone.recv(4)
header_size = struct.unpack('i'
,obj)[0]
#第二步: 再收報頭
header_bytes =phone.recv(header_size)
#第三步: 從報頭中解析出對真實資料的描述資訊
header_json = header_bytes.decode('
utf-8')
header_dic =json.loads(header_json)
(header_dic)
total_size = header_dic['
total_size']
#第四步: 接收真實的資料
recv_size=0
recv_data=b''
while recv_size res = phone.recv(1024)
recv_data +=res
recv_size +=len(res)
print(recv_data.decode('
gbk'
))phone.close()
tcp粘包現象
二 什麼時候需要考慮粘包問題?1 如果利用tcp每次傳送資料,就與對方建立連線,然後雙方傳送完一段資料後,就關閉連線,這樣就不會出現粘包問題 因為只有一種包結構,類似於http協議 關閉連線主要要雙方都傳送close連線 參考tcp關閉協議 如 a需要傳送一段字串給b,那麼a與b建立連線,然後傳送雙...
粘包現象與解決辦法
一 什麼是粘包現象 須知 只有tcp有粘包現象,udp永遠不會粘包 粘包不一定會發生,如果發生了 1.可能是在客戶端已經粘了,2.客戶端沒有粘,可能是在服務端粘了 粘包現象 tcp粘包是指傳送方傳送的若干包資料到接收方接收時粘成一包,從接收緩衝區看,後一包資料的頭緊接著前一包資料的尾。成因 所謂粘包...
粘包現象與解決方案
粘包是指兩次輸出結果粘到一起,它的發生主要是因為socket緩衝區導致的,粘包只在tcp中產生,不在udp產生 使用struct模組,先報頭長度進行打包發給客戶端,客戶端收到之後先解包報頭長度,再接收真實的資料 例子 服務端 usr bin env python3 coding utf 8 impo...