1.远程执行命令
2.粘包现象
3.解决粘包
远程执行命令:
新模块: subprocess
import subprocess
执行系统命令 #系统为GBK,不是"utf-8"
r = subprocess.Popen("ls",shell = True,stdout = subprocess.PIPE,stderr = subprocess.PIPE)
print(r.stdout.read().decode("gbk"))
print(r.stderr.read().decode("gbk"))
subprocess.Popen(a,b,c,d)
a:要执行的系统命令(str)
b:shell = True 表示确定我当前执行的命令为系统命令.
c: 表示正确信息的输出管道
d:表示错误信息的输出管道
tcp协议:面向数据流形式的特点.
tcp协议会发生粘包,因为两个机制,一个拆包机制,一个合包机制(nagle算法)
udp协议不会发生粘包,因为udp协议是面向数据包形式的通信
粘包:就是因为接收端不知道如何接收数据,造成了接收数据的混乱的问题.只发生在tcp协议上,因为tcp协议的特点是面向数据流形式的传输.粘包的发生主要是因为tcp协议有两个机制:合包机制(nagle算法),拆包机制
struct 模块:有一个方法,可以将一个21.3亿以内的数字,转变成一个固定长度的bytes数据类型,长度为4b.
res = struct.pack("i",num)
"i" : 表示的是int类型的数据
num : 表示要转换的数据类型
re = struct.unpack("i",res)将bytes数据转变回原数据
re是一个元祖,原数据保存在元祖的下标0的地方.
远程执行命令(客户端):
import socket
sk = socket.socket()
sk.connect_ex(("127.0.0.1",9090))
while 1:
a = input("请输入一个系统命令<<<")
sk.send(a.encode("utf-8"))
print(sk.recv(1024).decode("gbk")) #系统编码是以gbk 形式编码的.
sk.close()
远程执行命令(服务器):
import socket
import subprocess
sk = socket.socket()
sk.bind(("127.0.0.1",9090))
sk.listen()
conn,addr = sk.accept()
while 1:
ret = conn.recv(1024).decode("utf-8")
res = subprocess.Popen(ret,shell = True,stdout = subprocess.PIPE,stderr = subprocess.PIPE)
std_out = res.stdout.read() #读取正确的返回信息 , 是gbk数据的bytes类型
std_err =res.stderr.read() #读取错误的返回信息,是gbk数据的bytes类型
if std_out: #如果系统命令正确,条件为真.
conn.send(std_out)
else:
conn.send(std_err)
conn.close()
sk.close()
粘包现象(客户端):
import socket
sk= socket.socket()
sk.connect_ex(("127.0.0.1",9090))
sk.send(b"hello")
sk.send(b"world")
sk.close()
粘包现象(服务器):
import socket
sk=socket.socket()
sk.bind(("127.0.0.1",9090))
sk.listen()
conn,addr = sk.accept()
ret = conn.recv(1024)
res = conn.recv(1024)
print(ret)
print(res)
conn.close()
sk.close()
解决粘包现象(客户端(小文件)):
import socket
import os
import json
sk = socket.socket()
sk.connect_ex(("127.0.0.1",9090))
l = ["upload","download"]
for i,v in enumerate(l):
print(i+1,v)
dic = {"opt":None,"filename":None,"content":None}
while 1:
opt = input("请选择功能")
if opt == "1":
file_dir = input("请输入文件路径")
file_name = os.path.basename(file_dir)
with open(file_dir,encoding="utf-8")as f:
content = f.read()
dic["opt''] = l[int(opt)-1]
dic["filename"] = file_name
dic["content"] = content
dic = json.dumps(dic).encode("utf-8")
sk.send(dic)
elif opt == "2":
pass
else:
print("输入有误,请重新输入")
sk.close()
解决粘包现象(服务器端(小文件)):
import socket
import json
sk = socket.socket()
sk.bind(("127.0.0.1",9090))
sk.listen()
conn,addr = sk.accept()
dic_str = conn.recv(1024).decode("utf-8")
dic = json.loads(dic_str)
if dic["opt"] == "upload":
filename = "1" +dic["filename"]
with open(filename,"w",encoding = "utf-8")as f:
f.write(dic["content"])
elif dic["opt"] == "download":
pass
conn.close()
sk.close()
======================================
下边代码解决粘包现象,发送大文件
服务器端
import socket
import json
sk = socket.socket()
sk.bind(("127.0.0.1",9090))
sk.listen()
conn,addr = sk.accept()
dic_str = conn.recv(1024).decode(1024)
dic = json.loads(dic_str)
if dic["opt"] == "upload":
filename = "1" + dic["filename"]
with open(filename,"wb")as f:
while dic["filesize"]:
content = conn.recv(1024)
f.write(content)
dic["filesize"] -= len(content)
elif dic["opt"] == "download'':
pass
conn.close()
sk.close()
客户端
import socket
import os
import json
sk = socket.socket()
sk.connect(("127.0.0.1",9090))
l = ["upload","download"]
for i,v in enumerate(l):
print(i+1,v)
dic = {"opt":None,"fliename":None,"filesize":None}
while 1:
opt = input("请输入功能")
if opt == "1":
file_dir = input("请输入文件路径")
file_name = os.path.basename(file_dir)
file_size = os.path.basename(file_dir)
dic["opt"] = l[int(opt)-1]
dic["filename"] = file_name
dic["filesize"] = file_size
dic = json.dumps(dic).decode("utf-8")
sk.send(dic)
with open(file_dir,"rb")as f:
while file_size:
content = f.read(1024)
sk.send(content)
file_size -=len(content)
elif opt == "2":
pass
else:
print("输入有误,请重新输入")
sk.close()
============================================
最终版(客户端)
import socket
import os
import json
import struct
sk = socket.socket()
sk.connect((''127.0.0.1",9090))
l = ["upload","download"]
for i,v in enumerate(l):
print(i+1,v)
dic = {"opt":None,"filename":None,"filesize":None}
while 1:
opt = input("请输入功能选项")
if opt == "1":
file_dir = input("请输入文件路径")
file_name = os.path.basename(file_dir)
file_size = os.path.getsize(file_dir)
dic["opt"] = l[int(opt)-1]
dic["filename"] = file_name
dic["filesize"] = file_size
dic_str = json.dumps(dic)
dis = struct.pack("i",len(dic_str))
sk.send(dis+dic_str.encode("utf-8"))
with open(file_dir , "rb")as f:
while file_size:
content = f.read(1024)
sk.send(content)
file_size -= len(content)
elif opt == "2":
pass
else:
print("输入有误,请重新输入")
sk.close()
服务器端:
import socket
import json
import struct
sk= socket.socket()
sk.bind(("127.0.0.1",9090))
sk.listen()
conn,addr = sk.accept()
ret = conn.recv(4)
ret = struct.unpack("i",ret)
res = conn.recv(ret).decode("utf-8")
dic = json.loads(res)
if dic["opt"] == "upload":
filename = "1" + dic["filename"]
with open(filename,"wb")as f:
while dic["filename"]:
content = conn.recv(1024)
f.write(content)
dic["filename"] -= len(content)
elif dic["opt"] == "download":
pass
conn.close()
sk.close()