day34 远程执行命令,粘包现象和解决粘包

今日内容:

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()

猜你喜欢

转载自www.cnblogs.com/fengkun125/p/9343828.html