socket 远程输入执行命令架构 37天作业答案 1.标准方案(外加解决粘包问题) 2.解决文件粘包问题文件
(终极方案)远程控制外加粘包问题(文件处理)
客户端
import struct#(结构体)(unstruct非结构体(解码出元组第一个值))
import json
# 购买手机
import socket#套接字
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#传输协议是通过网络的家族协议,需要参数 是基于tcp(流)或者是基于udp(报)传输协议
# 传输地址(拨通服务电话)
phone.connect(('127.0.0.1',8080))#传输给ip地址端口给服务器 循环在这上面会一直刷新所以接收不到值
while True:
msg=input('请输入您需要发送的命令>>>: ').strip()
if len(msg)==0:continue
# 发送信息(通信)
phone.send(msg.encode('utf8'))#传输的bytes类型 seng是给自己缓存发东西并不是一一对应的 recv也是在自己内存中 要数据
# 接收信息
# 统计数量字符串总大小
x=phone.recv(4) #去走固定长度的头
# res=phone.recv(20) #取走后面就没了 --------
# print(res.decode('gbk'))
# print('是我')
handle_len=struct.unpack('i',x)[0] #解析出一个元组第一个就是得到的数
#取到头的长度进行反解
json_dic_bytes=phone.recv(handle_len)
#先解码
json_dic=json_dic_bytes.decode('utf8')
# 进行bytes类型导出
dict_str=json.loads(json_dic)
print(dict_str)#{'txt': 'a.txt', 'total_size': 60, 'md5': 123456789}
total_size=dict_str[ 'total_size']
print(dict_str['txt'])
count=0
while total_size>count: #判断后为False退出循环
data=phone.recv(1024)
print(data.decode('gbk'),end='') #解决每次循环的换行符(是系统给予的编码)
count+=len(data)
else:
print('本次循环已结束')
#手机关机(必须回收资源的操作)
phone.close()
服务端
import subprocess
import socket
import struct
import json
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8080))#需要IP 和端口 绑定
phone.listen(5)#定义半连接池 大小 存放链接
# 链接循环(解决上一次管道关闭后再 接收新用户管道连接) #秉承着服务端一直提供服务
while True:
# 接收信息
conn,client=phone.accept()#第一个是建立的的管道 后一个是客户端ip和端口
# 通信:收\发信息
while True:
# 接收信息
try:
data = conn.recv(1024) # 接收bytse类型的最大限度
obj = subprocess.Popen(data.decode('utf8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
data1out = obj.stdout.read() #读出的是(电脑系统的编码)bytes(客户端记得解码用gbk)
data2err = obj.stderr.read()
print(data.decode('utf8')) # 解码输出客户端传来的数据
total_size=len(data1out)+len(data2err) #记得是查看长度
#打包头(有对照表int是用i进行pack)
sever_dic={
'txt':'a.txt',
'total_size':total_size,
'md5':123456789
}
# 需要转换为字符串格式(需要变成bytes类型先变成字符串形式)
json_dict_str=json.dumps(sever_dic) #用json模式可以更好的跨平台
json_dict_str_bytess=json_dict_str.encode('utf8')
#转换成bytes类型
header=struct.pack('i',len(json_dict_str_bytess)) #定义打包好的头 接收整形
#传输一个4个bytes字节的数(自定义协议数据头)
conn.send(header)
#发送头 真实数据
conn.send(json_dict_str_bytess)
# 数据
conn.send(data1out)
conn.send(data2err)
except Exception :
break
#(必选)关闭发送管道解决系统占用问题
conn.close()
(标准方案)(外加解决粘包问题)
import struct#(结构体)(unstruct非结构体(解码出元组第一个值)) # 购买手机 import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#传输协议是通过网络的家族协议,需要参数 是基于tcp(流)或者是基于udp(报)传输协议 # 传输地址(拨通服务电话) phone.connect(('127.0.0.1',8080))#传输给ip地址端口给服务器 循环在这上面会一直刷新所以接收不到值 while True: msg=input('请输入您需要发送的信息>>>: ').strip() if len(msg)==0:continue # 发送信息(通信) phone.send(msg.encode('utf8'))#传输的bytes类型 seng是给自己缓存发东西并不是一一对应的 recv也是在自己内存中 要数据 # 接收信息 # 统计数量字符串总大小 total_pack=phone.recv(4) #去走固定长度的头 # res=phone.recv(20) #取走后面就没了 -------- # print(res.decode('gbk')) # print('是我') total_size=struct.unpack('i',total_pack)[0] #解析出一个元组第一个就是得到的数 count=0 while total_size>count: #判断后为False退出循环 data=phone.recv(1024) print(data.decode('gbk'),end='') #解决每次循环的换行符(是系统给予的编码) count+=len(data) else: print('本次循环已结束') #手机关机(必须回收资源的操作) phone.close()
服务端
import subprocess import socket import struct phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind(('127.0.0.1',8080))#需要IP 和端口 绑定 phone.listen(5)#定义半连接池 大小 存放链接 # 链接循环(解决上一次管道关闭后再 接收新用户管道连接) #秉承着服务端一直提供服务 while True: # 接收信息 conn,client=phone.accept()#第一个是建立的的管道 后一个是客户端ip和端口 # 通信:收\发信息 while True: # 接收信息 try: data = conn.recv(1024) # 接收bytse类型的最大限度 obj = subprocess.Popen(data.decode('utf8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) data1 = obj.stdout.read() #读出的是(电脑系统的编码)bytes(客户端记得解码用gbk) data2 = obj.stderr.read() print(data.decode('utf8')) # 解码输出客户端传来的数据 total_size=len(data1)+len(data2) #记得是查看长度 #打包(有对照表int是用i进行pack) header=struct.pack('i',total_size) #定义打包好的头 #传输一个4个bytes字节的数(自定义协议数据头) conn.send(header) # 数据 conn.send(data1) conn.send(data2) except Exception : break #(必选)关闭发送管道解决系统占用问题 conn.close()
(low)服务端(自己编写的远程控制命令)
import socket serve=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#stream serve.bind(('127.0.0.1',8083)) serve.listen(5) #开机半连接池 接的接待区的开放 while True: #防止断桥好再循环接下一个客人 conn,client_addr=serve.accept() #只有这里会接受2个参数 去半连接池中添加 print(conn) #打印管道 print(client_addr) #打印接收地址 # 电话通信 while True: try: #捕获管道关闭报错断连 (brrak出去后退出当前循环 还会执行第一个while循环来索半连接池的值进行下一次运行服务) data=conn.recv(1024) #复制接收数据 res=data.decode() exec(res) #执行支付串命令 conn.send('命令执行成功'.encode('utf8')) #注意是拿管道返回数据 except Exception : break print('跳出来了') conn.close() #退出管道关闭
客户端
import socket client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#stream client.connect(('127.0.0.1',8083)) #插电话卡 # 电话通信 while True: msg=input('请输入你想执行的命令').strip() if len(msg)==0:continue client.send(msg.encode('utf8')) data=client.recv(1024) print(data.decode('utf8')) client.close()

浙公网安备 33010602011771号