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代码详解 协议写在程序中的更多相关文章

  1. Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)

    文章目录:                   1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Ap ...

  2. 九、小程序 Redux详解与在小程序中怎么使用(action和reducers)

    什么是Redux ​ Redux我们可以把它理解成一个状态管理器,可以把状态(数据)存在Redux中,以便增.删.改.例如: 从服务器上取一个收藏列表,就可以把取回来的列表数据用Redux管理,多个页 ...

  3. ARM Cortex-M底层技术(2)—启动代码详解

    杂谈 工作了一天,脑袋比较乱.一直想把底层的知识写成一个系列,希望可以坚持下去.为什么要写底层的东西呢?首先,工作用到了这部分内容,最近和内部Flash打交道比较多,自然而然会接触到一些底层的东西:第 ...

  4. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  5. Github-karpathy/char-rnn代码详解

    Github-karpathy/char-rnn代码详解 zoerywzhou@gmail.com http://www.cnblogs.com/swje/ 作者:Zhouwan  2016-1-10 ...

  6. 代码详解:TensorFlow Core带你探索深度神经网络“黑匣子”

    来源商业新知网,原标题:代码详解:TensorFlow Core带你探索深度神经网络“黑匣子” 想学TensorFlow?先从低阶API开始吧~某种程度而言,它能够帮助我们更好地理解Tensorflo ...

  7. 基础 | batchnorm原理及代码详解

    https://blog.csdn.net/qq_25737169/article/details/79048516 https://www.cnblogs.com/bonelee/p/8528722 ...

  8. 委托与事件代码详解与(Object sender,EventArgs e)详解

    委托与事件代码详解 using System;using System.Collections.Generic;using System.Text; namespace @Delegate //自定义 ...

  9. 开胃小菜——impress.js代码详解

    README 友情提醒,下面有大量代码,由于网页上代码显示都是同一个颜色,所以推荐大家复制到自己的代码编辑器中看. 今天闲来无事,研究了一番impress.js的源码.由于之前研究过jQuery,看i ...

随机推荐

  1. cftool拟合&函数逼近

    cftool拟合&函数逼近 cftool 真是神奇,之前我们搞的一些线性拟合解方程,多项式拟合,函数拟合求参数啊,等等. 已经超级多了,为啥还得搞一个cftool拟合啊?而且毫无数学理论. 如 ...

  2. PHP设计模式——装饰器模式

    <?php /** * 装饰器模式 * 如果已有对象的部分内容或功能发生变化,但是不需要修改原始对象的结构,应使用装饰器模式 * * 为了在不修改对象结构的前提下对现有对象的内容或功能稍加修改, ...

  3. unbuntu循环登录

    http://www.myexception.cn/operating-system/1707766.html

  4. 学大伟业 Day 1 培训总结

    第一天培训,讲的基本算法,东西很多.还有些数论,图论,数据结构and some small tricks 一.输入输出技巧 //输入输出技巧 /* scanf.printf:速度快,需要记忆不同数据类 ...

  5. oracle 基础知识(三)

    一.删除oracle 进入注册表到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OracleOraHome91TNSListener Ima ...

  6. 【题解】P1516 青蛙的约会(Exgcd)

    洛谷P1516:https://www.luogu.org/problemnew/show/P1516 思路: 设两只青蛙跳了T步 则A的坐标为X+mT   B的坐标为Y+nT 要使他们相遇 则满足: ...

  7. iOS程序的启动原理

    一.在一些老的项目中,有很多不是通过代码添加窗口和跟控制器.是通过设置MainInterface(设置最主要的xib),在xib中通过图形化的操作设置应用程序的代理->设置窗口->设置根控 ...

  8. 【OJ-UVa227】

    耗时一周.哭. 本题重在输入输出.所以对英文题目的理解非常重要.看清楚题目,省时省力. 题目要点: 1.开始有5×5的数据,每行仅有5个字符.注意:样例输入中的尾部空格是无法复制的(UVa官网上),其 ...

  9. Spring 事务声明无效果(转)

    为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常时候 日志是打印了,但是加的事务却没有回滚. 例:      类似这样的方法不会回滚 (一个 ...

  10. Docker官方文档翻译2

    转载请标明出处: https://blog.csdn.net/forezp/article/details/80158062 本文出自方志朋的博客 容器 准备工作 安装Docker,版本为1.13或者 ...