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代码详解 协议写在程序中的更多相关文章
- Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)
文章目录: 1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Ap ...
- 九、小程序 Redux详解与在小程序中怎么使用(action和reducers)
什么是Redux Redux我们可以把它理解成一个状态管理器,可以把状态(数据)存在Redux中,以便增.删.改.例如: 从服务器上取一个收藏列表,就可以把取回来的列表数据用Redux管理,多个页 ...
- ARM Cortex-M底层技术(2)—启动代码详解
杂谈 工作了一天,脑袋比较乱.一直想把底层的知识写成一个系列,希望可以坚持下去.为什么要写底层的东西呢?首先,工作用到了这部分内容,最近和内部Flash打交道比较多,自然而然会接触到一些底层的东西:第 ...
- BM算法 Boyer-Moore高质量实现代码详解与算法详解
Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...
- Github-karpathy/char-rnn代码详解
Github-karpathy/char-rnn代码详解 zoerywzhou@gmail.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2016-1-10 ...
- 代码详解:TensorFlow Core带你探索深度神经网络“黑匣子”
来源商业新知网,原标题:代码详解:TensorFlow Core带你探索深度神经网络“黑匣子” 想学TensorFlow?先从低阶API开始吧~某种程度而言,它能够帮助我们更好地理解Tensorflo ...
- 基础 | batchnorm原理及代码详解
https://blog.csdn.net/qq_25737169/article/details/79048516 https://www.cnblogs.com/bonelee/p/8528722 ...
- 委托与事件代码详解与(Object sender,EventArgs e)详解
委托与事件代码详解 using System;using System.Collections.Generic;using System.Text; namespace @Delegate //自定义 ...
- 开胃小菜——impress.js代码详解
README 友情提醒,下面有大量代码,由于网页上代码显示都是同一个颜色,所以推荐大家复制到自己的代码编辑器中看. 今天闲来无事,研究了一番impress.js的源码.由于之前研究过jQuery,看i ...
随机推荐
- python入门4 python查看数据类型及类型转换
查看数据类型:type() 类型转换:int(),float(),char(),ord(),str(),bool() #coding:utf-8 #/usr/bin/python "&quo ...
- BZOJ3262:陌上花开(CDQ分治)
Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),用三个整数表示. 现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量. 定义一朵花A比另一朵花B要美 ...
- PIL 一秒切九图 朋友圈发图神器
注意图片像素返回值是(宽度,高度),pil填像素点坐标原点左上角. 判断像素点是否在圆方程中. import numpy as np from PIL import Image file = inpu ...
- 【Elasticsearch】搜索小记之 match VS match_phrase
最近稍微研究了一下ElasticSearch(下文简称ES),所谓可扩展的开源弹性搜索解决方案,跟同事笑称,如果它作为SQL SERVER的话,我的了解还在基本的select语句上,当然学习它也是一个 ...
- 原生ajax、XMLHttpRequest和FetchAPI简单描述
什么是ajax ajax的出现,刚好解决了传统方法的缺陷.AJAX 是一种用于创建快速动态网页的技术.通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个 ...
- 使用actionerror做失败登录验证
一. 登录页面中放置如下代码: <h4>员工登录</h4> <div style="color:red"> <s:actionerror/ ...
- Swift_控制流
Swift_控制流 点击查看源码 for-in 循环 //for-in 循环 fileprivate func testForIn() { //直接循环提取内部数据 //[1,5] for index ...
- LeetCode 中级 - 第k个排列(60)
可以用数学的方法来解, 因为数字都是从1开始的连续自然数, 排列出现的次序可以推 算出来, 对于n=4, k=15 找到k=15排列的过程: 1 + 对2,3,4的全排列 (3!个) 2 + 对1,3 ...
- 2018 Wannafly summer camp Day3--Shopping
Shopping 描述 题目描述: 你要买n件物品,其中有一些是凳子. 商场正在举行促销活动,如果购物车中有至少一个凳子,那么你可以半价购买这个购物车中最贵的一个物品. 你有m辆购物车,请最小化你的花 ...
- 【PTA 天梯赛训练】词频统计(map+vector)
请编写程序,对一段英文文本,统计其中所有不同单词的个数,以及词频最大的前10%的单词. 所谓“单词”,是指由不超过80个单词字符组成的连续字符串,但长度超过15的单词将只截取保留前15个单词字符.而合 ...