• Python UDP 协议网络编程《六》


    今日主题:Python 实现的使用命令行进行文件下载的功能。

    温馨提示:
    今日内容与前期推文Python UDP 协议网络编程《四》具有一定的关联性,是在该文章的基础上进行的再一次改造。如果Python UDP 协议网络编程《四》没有阅读的小伙伴,建议先阅读后,再来学习今天的内容,会有一个比较直观的对比。(点击蓝色字体的推文名称即可查看上一篇文章全部内容)。

    今日分享内容与已分享的Python UDP 协议网络编程系列推文一样,理论内容较少,今天更偏实战性,以下实现代码需仔细分析、理解每一行代码的作用及相互间的关联关系,可与Python UDP 协议网络编程《四》实现的功能进行对比,相信你会发现其中的不同。

    同时建议小伙伴们自行搭建本地环境将代码运行起来,在解决问题的过程中,通过思考与实践才能更好的理解本文主题。

     1import sys
     2import struct
     3from socket import socket,AF_INET,SOCK_DGRAM
     4
     5filename=""#定义要下载的文件名
     6ftp_server_ip=""#定义服务器的ip地址
     7username=""#用户名
     8password=""#密码
     9
    10def run_cmd():
    11    global filename,ftp_server_ip,username,password
    12    if(len(sys.argv)!=3):
    13        print("命令行格式不对,请参照以下标准")
    14        print("="*100)
    15        print("for example:")
    16        print()
    17        print("python python_tftp_download.py username:password@ftp_server_ip filename")
    18        print("=" * 100)
    19        exit()
    20    else:
    21        filename=sys.argv[2]
    22        all=sys.argv[1]
    23        username=str(all).split(":")[0]
    24        password=str(all).split("@")[0].split(":")[1]
    25        ftp_server_ip=str(all).split("@")[1]
    26        print(ftp_server_ip)
    27
    28def download_file():
    29    print("step1:准备开始下载"+filename+"文件")
    30    send_data=struct.pack("!H%dsb5sb"%len(filename),1,filename.encode("utf-8"),0,b'octet',0) #封装一个读文件请求,上面的步骤1
    31    print("step2:建立一个udp socket连接")
    32    udp_socket=socket(AF_INET,SOCK_DGRAM) #创建一个udp socket
    33    print("step3:向tftp ip=127.0.0.1 port=69服务器发送读写请求")
    34    udp_socket.sendto(send_data,(ftp_server_ip,69)) #向tftp 服务器发送读写请求
    35    print("step4:新建一个文件句柄,为了接收想下载的文件内容")
    36    fhandle=open(filename,'ab')#在本地创建一个文件,a表示追加,b表示二进制
    37    while 1:
    38        print("step5:开始接收消息,消息内容为接收的数据和服务器信息")
    39        recv_data,server_info=udp_socket.recvfrom(1024) #接收数据,返回的是二维元组,第一个是接收的数据,第二个是服务器ip and port,上面的步骤2
    40        operation_code=struct.unpack("!H",recv_data[:2]) #获取操作码
    41        ack_num=struct.unpack("!H",recv_data[2:4]) #获取数据块
    42        print("step6: 获取操作码:", operation_code, "和数据块编号", ack_num)
    43        print("step7: 打印:the server of info is:",server_info)
    44        if operation_code==5:#5就是错误码
    45            print("the file is not found")
    46            break
    47        print("step8:打印接收的数据:",recv_data)
    48        print("step9:开始写文件")
    49        fhandle.write(recv_data[4:])#写内容到文件,因为前四个字节是操作码和数据块,所以要从第四位开始写文件
    50        print("step10:判断文件是否读取完成")
    51        if(len(recv_data)<516):#判断文件是否读取完成,上面的步骤4
    52            fhandle.close()
    53            break
    54        '''
    55        3、ACK
    56        操作码  +  块编码
    57        2Bytes     2Bytes
    58        '''#因为发布ACK包的操作码与块编码都是2个字节,所以如下用的是HH
    59        print("step10:封装确认包信息")
    60        send_data1=struct.pack("!HH",4,ack_num[0]) #封装确认包信息
    61        print("step11:获取服务器端ip and port")
    62        server_port=server_info[1]#获取服务器端发送数据的随机端口
    63        server_address=server_info[0]
    64        print("step12:发送ACK 确认包信息")
    65        udp_socket.sendto(send_data1,(server_address,server_port))#发送确认包信息,上面的步骤3
    66    print("step13:文件"+filename+"下载成功!!!")
    67
    68def user_login(data):
    69    udp_socket = socket(AF_INET, SOCK_DGRAM)  # 建议upd连接
    70    local_address = ('127.0.0.1', 8001)  # 定义了本机的ip and port
    71    udp_socket.bind(local_address)  # 绑定本机的ip and port
    72    resvice_address=('127.0.0.1', 69) #定义了接收消息机器的ip and port
    73    udp_socket.sendto(str(data).encode("utf-8"),resvice_address)#向接收消息机器发送消息
    74    print("登录成功")
    75    udp_socket.close()
    76    udp_secv_msg()
    77
    78def udp_secv_msg():
    79    print("开始接收消息")
    80    udp_sockets = socket(AF_INET, SOCK_DGRAM)  # 建立udp socker连接
    81    server_address = (ftp_server_ip, 70)  # 定义了服务端的ip and port
    82    udp_sockets.bind(server_address)  # 服务端绑定ip and port
    83    print("正在接收消息")
    84    recv_data = udp_sockets.recvfrom(1024)  # 收数据等待
    85    print("the data is:",recv_data)
    86    print('接收的内容:', recv_data[0].decode('utf-8'))  # 显示收到的信息
    87    print('发送人的地址:', recv_data[1])  # 显示收到的信息
    88    udp_sockets.close()
    89
    90if __name__ == '__main__':
    91    #命令格式校验
    92    run_cmd()
    93    data = username+" "+password
    94    print(data)
    95    #第一步登录tftp服务器
    96    user_login(data)
    97    #第二步是下载文件
    98    download_file()

    执行结果为:

     1 执行的结果为:
     2 (venv) D:BaiduNetdiskDownloadows-projectwechatdocker-compose1>python pythonFFTP_download_command.py admin:123456@127.0.0.1 requirements.txt
     3 127.0.0.1
     4 admin 123456
     5 登录成功
     6 开始接收消息
     7 正在接收消息
     8 the data is: (b'xe7x99xbbxe5xbdx95xe6x88x90xe5x8ax9f,xe5x8fxafxe4xbbxa5xe5xbcx80xe5xa7x8bxe4xb8x8axe4xbcxa0xe4xb8x8bxe8xbdxbdx
     9 e6x96x87xe4xbbxb6xe4xbax86xefxbcx81xefxbcx81xefxbcx81', ('127.0.0.1', 8000))
    10 接收的内容: 登录成功,可以开始上传下载文件了!!!
    11 发送人的地址: ('127.0.0.1', 8000)
    12 step1:准备开始下载requirements.txt文件
    13 step2:建立一个udp socket连接
    14 step3:向tftp ip=127.0.0.1 port=69服务器发送读写请求
    15 step4:新建一个文件句柄,为了接收想下载的文件内容
    16 step5:开始接收消息,消息内容为接收的数据和服务器信息
    17 step6: 获取操作码: (3,) 和数据块编号 (0,)
    18 step7: 打印:the server of info is: ('127.0.0.1', 64495)
    19 step8:打印接收的数据: b'x00x03x00x00flask
    redis
    pymysqlflask
    redis
    pymysql'
    20 step9:开始写文件
    21 step10:判断文件是否读取完成
    22 step13:文件requirements.txt下载成功!!!

    欢迎关注【无量测试之道】公众号,回复【领取资源】,
    Python编程学习资源干货、
    Python+Appium框架APP的UI自动化、
    Python+Selenium框架Web的UI自动化、
    Python+Unittest框架API自动化、

    资源和代码 免费送啦~
    文章下方有公众号二维码,可直接微信扫一扫关注即可。

    备注:我的个人公众号已正式开通,致力于测试技术的分享,包含:大数据测试、功能测试,测试开发,API接口自动化、测试运维、UI自动化测试等,微信搜索公众号:“无量测试之道”,或扫描下方二维码:

     添加关注,让我们一起共同成长!

  • 相关阅读:
    HTML5新增
    【目录】洛谷|CODEVS题解汇总
    【搜索】kkksc03考前临时抱佛脚
    【模拟】压缩技术
    【模拟】爱与愁的一千个伤心的理由
    【搜索】棋盘
    【模拟】图书管理员
    【递归】对称二叉树
    【题单】挖坑大行动
    【模拟】弹珠游戏
  • 原文地址:https://www.cnblogs.com/Wu13241454771/p/13816722.html
Copyright © 2020-2023  润新知