解决tcp协议的粘包问题

一、远程执行命令的程序

 

服务端:

from socket import *
import subprocess

server=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
conn,client_addr=server.accept() #(连接对象,客户端的ip和端口)
print(client_addr)
while True:
try:
cmd=conn.recv(1024)
if len(cmd)==0:break

obj=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE

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


conn.send(stdout+stderr)

except ConnectionResetError:
break

conn.close()
server.close()


客户端:
from socket import *

client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
# print(client)

while True:
cmd=input('>>>: ').strip()
if not cmd:continue
client.send(cmd.encode('utf-8'))
res=client.recv(1024)
print(res.decode('gbk'))

client.close()


二、解决tcp协议的粘包问题

补充struct模块:
    1、把整形数字转成bytes类型
    2、转成的bytes固定长度


服务端:

from socket import *
import subprocess
import struct
import json

server=socket(AF_INET,SOCK_STREAM)
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'
if len(cmd) == 0:break

# 运行系统命令
obj=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE
)

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

#先制作报头
header_dic={
'filename':'a.txt',
'total_size':len(stdout) + len(stderr),
'hash':'xasf123213123'
}
header_json=json.dumps(header_dic)
header_bytes=header_json.encode('utf-8')

#1、先把报头的长度len(header_bytes)打包成4个bytes,然后发送
conn.send(struct.pack('i',len(header_bytes)))
#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]

#2、再接收报头
header_bytes=client.recv(header_len)

#从报头中解析出想要的内容
header_json=header_bytes.decode('utf-8')
header_dic=json.loads(header_json)
print(header_dic)
total_size=header_dic['total_size']


#3、再收真实的数据
recv_size=0
res=b''
while recv_size < total_size :
data=client.recv(1024)
res+=data
recv_size+=len(data)

print(res.decode('gbk'))

 

posted @ 2018-07-11 18:38  Shinonon  阅读(188)  评论(0编辑  收藏  举报