8 TFTP代码详解 协议写在程序中

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8 TFTP代码详解 协议写在程序中相关的知识,希望对你有一定的参考价值。

1.版本1:发送请求

# -*- coding:utf-8 -*-

import struct
from socket import *

#0. 获取要下载的文件名字:
downloadFileName = raw_input("请输入要下载的文件名:")    

#1.创建socket
udpSocket = socket(AF_INET, SOCK_DGRAM)

requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0)

#2. 发送下载文件的请求
udpSocket.sendto(requestFileData, ("192.168.119.215", 69))

  技术分享图片

 

2.版本2:回复ack

# -*- coding:utf-8 -*-

import struct
from socket import *

#0. 获取要下载的文件名字:
downloadFileName = raw_input("请输入要下载的文件名:")    

#1.创建socket
udpSocket = socket(AF_INET, SOCK_DGRAM)

requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0)

#2. 发送下载文件的请求
udpSocket.sendto(requestFileData, ("192.168.119.215", 69))



#3. 接收服务发送回来的应答数据
responseData = udpSocket.recvfrom(1024)

# print(responseData)
recvData, serverInfo = responseData

opNum = struct.unpack("!H", recvData[:2])

packetNum = struct.unpack("!H", recvData[2:4])

print(packetNum[0])

 

   技术分享图片

 

 

3.版本3:while True 循环

# -*- coding:utf-8 -*-

import struct
from socket import *
import time
import os

def main():


    #0. 获取要下载的文件名字:
    downloadFileName = raw_input("请输入要下载的文件名:")    

    #1.创建socket
    udpSocket = socket(AF_INET, SOCK_DGRAM)
    requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0)

    #2. 发送下载文件的请求
    udpSocket.sendto(requestFileData, ("192.168.119.215", 69))


    while True:
        #3. 接收服务发送回来的应答数据
        responseData = udpSocket.recvfrom(1024)
        # print(responseData)
        recvData, serverInfo = responseData
        opNum = struct.unpack("!H", recvData[:2])
        packetNum = struct.unpack("!H", recvData[2:4])
        print(packetNum[0])

        time.sleep(0.1)

if __name__ == __main__:
    main()

 

 

4.版本4:跳出循环

# -*- coding:utf-8 -*-

import struct
from socket import *
import time
import os

def main():


    #0. 获取要下载的文件名字:
    downloadFileName = raw_input("请输入要下载的文件名:")    

    #1.创建socket
    udpSocket = socket(AF_INET, SOCK_DGRAM)
    requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0)

    #2. 发送下载文件的请求
    udpSocket.sendto(requestFileData, ("192.168.119.215", 69))

    flag = True #表示能够下载数据,即不擅长,如果是false那么就删除
    num = 0
    f = open(downloadFileName, "w")

    while True:
        #3. 接收服务发送回来的应答数据
        responseData = udpSocket.recvfrom(1024)
        # print(responseData)
        recvData, serverInfo = responseData
        opNum = struct.unpack("!H", recvData[:2])
        packetNum = struct.unpack("!H", recvData[2:4])
        print(packetNum[0])

        time.sleep(0.1)

        if len(recvData)<516:
            break


if __name__ == __main__:
    main()

 

 

 

5.版本5:优化版本,文件不存在

# -*- coding:utf-8 -*-

import struct
from socket import *
import time
import os

def main():


    #0. 获取要下载的文件名字:
    downloadFileName = raw_input("请输入要下载的文件名:")    

    #1.创建socket
    udpSocket = socket(AF_INET, SOCK_DGRAM)

    requestFileData = struct.pack("!H%dsb5sb"%len(downloadFileName), 1, downloadFileName, 0, "octet", 0)

    #2. 发送下载文件的请求
    udpSocket.sendto(requestFileData, ("192.168.119.215", 69))

    flag = True #表示能够下载数据,即不擅长,如果是false那么就删除
    num = 0
    f = open(downloadFileName, "w")

    while True:
        #3. 接收服务发送回来的应答数据
        responseData = udpSocket.recvfrom(1024)

        # print(responseData)
        recvData, serverInfo = responseData

        opNum = struct.unpack("!H", recvData[:2])

        packetNum = struct.unpack("!H", recvData[2:4])

        print(packetNum[0])

        # print("opNum=%d"%opNum)
        # print(opNum)

        # if 如果服务器发送过来的是文件的内容的话:
        if opNum[0] == 3: #因为opNum此时是一个元组(3,),所以需要使用下标来提取某个数据
            

            #计算出这次应该接收到的文件的序号值,应该是上一次接收到的值的基础上+1
            num = num + 1

            # 如果一个下载的文件特别大,即接收到的数据包编号超过了2个字节的大小
            # 那么会从0继续开始,所以这里需要判断,如果超过了65535 那么就改为0
            if num==65536:
                num = 0

            # 判断这次接收到的数据的包编号是否是 上一次的包编号的下一个
            # 如果是才会写入到文件中,否则不能写入(因为会重复)
            if num == packetNum[0]:
                # 把收到的数据写入到文件中
                f.write(recvData[4:])
                num = packetNum[0]

            #整理ACK的数据包
            ackData = struct.pack("!HH", 4, packetNum[0])
            udpSocket.sendto(ackData, serverInfo)

        elif opNum[0] == 5:
            print("sorry,没有这个文件....")
            flag = False

        # time.sleep(0.1)

        if len(recvData)<516:
            break

    if flag == True:
        f.close()
    else:
        os.unlink(downloadFileName)#如果没有要下载的文件,那么就需要把刚刚创建的文件进行删除

if __name__ == __main__:
    main()

 

 

 

6.版本6:第二种参考程序

#coding=utf-8

from socket import *
import struct
import sys

if len(sys.argv) != 2:
    print(-*30)
    print("tips:")
    print("python xxxx.py 192.168.1.1")
    print(-*30)
    exit()
else:
    ip = sys.argv[1]

# 创建udp套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)

#构造下载请求数据
cmd_buf = struct.pack("!H8sb5sb",1,"test.jpg",0,"octet",0)

#发送下载文件请求数据到指定服务器
sendAddr = (ip, 69)
udpSocket.sendto(cmd_buf, sendAddr)

p_num = 0

recvFile = ‘‘

while True:
    recvData,recvAddr = udpSocket.recvfrom(1024)

    recvDataLen = len(recvData)

    # print recvAddr # for test

    # print len(recvData) # for test

    cmdTuple = struct.unpack("!HH", recvData[:4])

    # print cmdTuple # for test

    cmd = cmdTuple[0]
    currentPackNum = cmdTuple[1]        

    if cmd == 3: #是否为数据包

        # 如果是第一次接收到数据,那么就创建文件
        if currentPackNum == 1:
            recvFile = open("test.jpg", "a")

        # 包编号是否和上次相等
        if p_num+1 == currentPackNum:
            recvFile.write(recvData[4:]);
            p_num +=1
            print (%d)次接收到的数据%(p_num)

            ackBuf = struct.pack("!HH",4,p_num)

            udpSocket.sendto(ackBuf, recvAddr)
        # 如果收到的数据小于516则认为出错
        if recvDataLen<516:
            recvFile.close()
            print 已经成功下载!!!
            break

    elif cmd == 5: #是否为错误应答
        print "error num:%d"%currentPackNum
        break

udpSocket.close()

 

以上是关于8 TFTP代码详解 协议写在程序中的主要内容,如果未能解决你的问题,请参考以下文章

Swoole 关于reload重启与回调函数中代码的重载

TFTP协议详解及TFTP穿越NAT

tftp命令详解

java中代码发生异常后 程序会怎么执行?

怎样查看DSP程序中代码的运行时间,该如何处理

统计c程序中代码行数以及函数的个数