zoukankan      html  css  js  c++  java
  • TCP协议中传输系统命令及上传下载文件

    传输系统命令

    1 执行命令:

          在py代码中如何去调用操作系统的命令

    新模块 :  subprocess

    r = subprocess.Popen('ls',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)

      subprocess.Popen(cmd,shell=True,subprocess.stdout,subprocess.stderr)
      cmd :
    代表系统命令
      shell = True   代表这条命令是 系统命令,告诉操作系统,将cmd当成系统命令去执行
      stdout   是执行完系统命令之后,用于保存结果的一个管道
      stderr   是执行完系统命令之后,用于保存错误结果的一个管道

    服务器代码
    import socket
    import subprocess
    
    sk = socket.socket()
    sk.bind(('127.0.0.1',8080))
    sk.listen()
    
    conn,addr = sk.accept()
    while 1:
        cmd = conn.recv(1024).decode('utf-8')
        r = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        stdout = r.stdout.read()
        stderr = r.stderr.read()
        if stderr:
            conn.send(stderr)
        else:
            conn.send(stdout)
    
    conn.close()
    sk.close()
    
    
    用户端代码
    # 客户端发送要执行命令
    # 服务器执行,执行完将结果返回给客户端
    # 客户端拿到结果呈现到用户眼前
    
    import socket
    
    sk = socket.socket()
    
    sk.connect_ex(('127.0.0.1',8080))
    while 1:
        cmd = input('请输入一个命令>>>')
        sk.send(cmd.encode('utf-8'))
    
        result = sk.recv(102400).decode('gbk')
    
        print(result)
    
    
    sk.close()
    

    上传下载文件

    服务器代码
    import socket   #大文件传输
    import json
    import struct
    
    sk = socket.socket()
    sk.bind(("127.0.0.1",9888))
    sk.listen()
    
    # conn,addr = sk.accept()
    
    while 1:
        conn, addr = sk.accept()
        b_dic = conn.recv(4)  # 先接收bytes类型的4个字节
        len_dic = struct.unpack("i", b_dic)[0]  # 转换成原来字典的长度
        str_r = conn.recv(len_dic).decode("utf-8")
        r = json.loads(str_r)
        if r["choose"] == "upload":
            with open (r["file"],"rb")as f:
                while r["filesize"]:
                    count = f.read(1024)
                    conn.send(count)
                    r["filesize"] -= len(count)
    
        if r["choose"] == "download":
            with open (r["file"],"rb")as f:
                while r["filesize"]:
                    count = f.read(1024)
                    conn.send(count)
                    r["filesize"] -= len(count)
    conn.clsoe()
    sk.close()
    
    
    
    客户端代码
    import socket     #大文件传输
    import os
    import json
    import struct
    
    sk = socket.socket()
    sk.connect(("127.0.0.1",9888))
    while 1:
        print("""1,upload
    2,download
    3,out""")
        num = input("请输入要选择的选项:")
        if num == "1":
            file = input("请输入要上传文件的绝对路径:")
            filename = os.path.basename(file)
            filesize = os.path.getsize(file)
            dic = {"choose":"upload","file":file,"filesize":filesize}
    
            str_dic = json.dumps(dic) #再将字典序列化成字符串
            b_dic = struct.pack("i", len(str_dic))  # 将字典的长度转换成4个字节的bytes数据
            sk.send(b_dic + str_dic.encode("utf-8")) #将这两个bytes类型的数据发送给服务器端
    
            with open ("1"+filename,"ab")as f:
                while filesize:
                    count = sk.recv(1024)
                    f.write(count)
                    filesize -= len(count)
            #C:/Users/duansir/Desktop/知识点/测试.py
        if num == "2":
            file =input("请输入要下载文件的绝对路径:")
            file2 = input("请输入储存下载文件的绝对路径:")
            filename = os.path.basename(file)
            # filename2 = os.path.basename(file2)
            filesize = os.path.getsize(file)
            dic = {"choose":"download","file":file,"filesize":filesize,"file2":file2}
            str_dic = json.dumps(dic)
            b_dic = struct.pack("i", len(str_dic))  # 将字典的长度转换成4个字节的bytes数据
            sk.send(b_dic + str_dic.encode("utf-8"))  # 将这两个bytes类型的数据发送给服务器端
            # sk.send(str_dic.encode("utf-8"))
            with open (file2+"/"+"1"+filename,"ab")as f:
                fs = filesize
                s = 0
                while filesize:
                    count = sk.recv(1024)
                    f.write(count)
                    filesize -= len(count)
                    s += 1024
                    num = round(s/fs,1)
                    num1 = int(num*10)
                    print("
    "+num1*1*"■"+str(num1*10)+"%",end="")
                else:
                    print()
    
        if num == "3":
            break
    sk.close()
    

      

      

    黏包

      只有tcp协议才会发生黏包,udp不会发生

    EX:  发送端发送数据,接收端不知道应该如何去接收,造成的一种数据混乱的现象

         在tcp协议中,

       1,有一个合包机制(nagle算法),将多次连续发送且间隔较小的数据,进行打包成一块数据传送.

       2,还有一个机制是拆包机制,在发送端,因为受到网卡的MTU限制,会将大的超过MTU限制的数据,进行拆分,拆分成多个小的数据,进行传输.  当传输到目标主机的操作系统层时,会重新将多个小的数据合并成原本的数据

    针对 使用udp协议发送数据,一次收发大小究竟多少合适?

    udp不会发生粘包,udp协议本层对一次收发数据大小的限制是:65535 - ip包头(20) - udp包头(8) = 65507

    站在数据链路层,因为网卡的MTU一般被限制在了1500,所以对于数据链路层来说,一次收发数据的大小被限制在  1500 - ip包头(20) - udp包头(8) = 1472

    得到结论:

        如果sendto(num)

         num > 65507  报错

         1472 < num < 65507  会在数据链路层拆包,而udp本身就是不可靠协议,所以一旦拆包之后,造成的多个小数据包在网络传输中,如果丢任何一个,那么此次数据传输失败

         num < 1472 是比较理想的状态

  • 相关阅读:
    .net core 2.2, new Bitmap出错 The type initializer for 'Gdip' threw an exception
    瑞萨单片机学习笔记(待续)
    Linux-GitLab安装及汉化
    mysql5.7 ibtmp1文件过大
    #和$的区别
    RTP封装h264
    一个项目同时需要向两个地址推送
    git命令
    echart绘制进度条、仪表盘、各种样式的折线图、饼图、环形图、地图等
    前端在实现类似控制台命令行或者告警信息提示时,需要保持滚动条始终停留在最新的信息位置,也就是最底部
  • 原文地址:https://www.cnblogs.com/duanpengpeng/p/9475658.html
Copyright © 2011-2022 走看看