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. python入门13 集合set

    set集合与数学中的集合同一个概念,是无序不重复元素组成的. #coding:utf-8 #/usr/bin/python """ 2018-11-10 dinghanh ...

  2. python入门5 运算符

    python运算符: 1 算术运算符 加减乘除 取余 求商 求幂等 2 比较运算符==   !=  >  >=  < <= 3 逻辑运算符 and  not  or 4 赋值运 ...

  3. Android(java)学习笔记10:同步中的死锁问题以及线程通信问题

    1. 同步弊端: (1)效率低 (2)如果出现了同步嵌套,就容易产生死锁问题 死锁问题及其代码 : (1)是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象 (2)同步代码块的 ...

  4. 成都夏季招聘会IT行业缺口大!

    上个周末成都的夏季招聘会在新会展中心举行,我们传智播客的专业市场调查员也深入当中.了解IT行业招聘情况,我们发如今IT软件行业专区招聘的公司特别多,可是去应聘的人却非常少.这意味着IT行业正处于供不应 ...

  5. Windows7安装Envi4.8简体中文破解版

    在正式安装前,建议先完整阅读本教程!本教程所使用的是Envi 4.8 32 位安装包,径测试,在64位windows7上可以正常安装使用!本教程就是在64位windows7上安装32位Envi4.8! ...

  6. 初入AngularJS基础门

    作为mvvm 框架过重 不适用于性能比较高的移动端的web栈, ui组建性对复杂,不利于重用 AngularJS 构建一个CRUD ( create retrieve update delete )的 ...

  7. OS_EVENT 信号量

    1.   OS_EVENT *T2sem=(OS_EVENT *)0; 这句代码的意思是 把OS_EVENT类型的一个指针T2sem赋值为0: 其中 OS_EVENT是数据类型,*代表是指针类型,(O ...

  8. c语言描述的双向链表的基本操作

    #include<stdio.h> #include<stdlib.h> #define ok 1 #define error 0 typedef int Status; ty ...

  9. C# sqlhelp

    public class SqlHelp { //数据库连接字符串 public static string connectionString = ConfigurationManager.Conne ...

  10. c# 任务超时执行组件

    最近整理下各类框架,学习一下欠缺的东西.因为前一年开发过java服务端,知道java有很多开源框架,但是毕竟起来也很累. 现在转回头从新审视c#,很基础,没有开源框架,因为以前它不开源,所以少,不用比 ...