TFTP实现 / TFTP Implement


目录

  1. TFTP 的服务器建立过程
  2. TFTP 的客户端建立过程

1 TFTP 的服务器建立过程

服务器建立步骤主要有:

(1)      设定服务器IP和端口号(常用69),建立socket并bind地址;

(2)      设定服务器工作目录;

(3)      建立主循环进行监听,根据收到的信息选择读/写模式;

(4)      (建立新的线程及socket)执行上传下载操作;

(5)      下载操作: block number设置为1—打开需要下载的文件—进入循环—读取512byte数据—发送读取的数据—等待ACK报文(超时重发)—确认opcode—确认数据长度是否结束(结束则进行结束处理,并关闭文件)11—block number +1;

(6)      上传操作: block number 设置为0—发送ACK报文—block number +1—打开新的文件存储上传数据—进入循环—等待接收DATA报文—确认opcode—写入数据—发送ACK报文—确认数据长度是否结束(结束则进行结束处理,并关闭文件)—block number +1。

Note: 关于THTP_Helper 的 TFTP 的加解码过程请参考 TFTP 加解码部分

 import importlib
from TFTP_Helper import *
import socket
from threading import Thread class TFTPServer():
def __init__(self):
ip = '127.0.0.1'
port = 69
address = (ip, port)
self.home_path = 'TFTPServerFile'
self.server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.server.bind(address) def readRequest(self, file_name, addr):
print('<<< RRQ', '\n=== Read request, starting file %s downing to client' % file_name, end='')
sock_down = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
block_num = 1
try:
f = open(self.home_path + '\\' + file_name, 'rb')
except:
# file no found, exit thread
print('=== File %s no found' % file_name)
exit()
while True:
down_data = f.read(512) # data is byte format
sock_down.sendto(TFTPData.encode(block_num, down_data), addr)
print('>>> DATA', block_num)
ack_msg, ack_addr = sock_down.recvfrom(1024)
print('<<< ACK ', block_num)
opcode, ack_block_num = TFTPAck.decode(ack_msg)
assert opcode == 4 and ack_block_num == block_num, 'Invalid ack message.'
if len(down_data) < 512:
block_num = 1
print('=== Transmission of %s completed' % file_name)
f.close()
exit()
block_num += 1
print('=== Close file')
f.close() def writeRequest(self, file_name, addr):
print('<<< WRQ', '\n=== Write request, starting file %s uploading to server' % file_name)
sock_upload = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
block_num = 0
sock_upload.sendto(TFTPAck.encode(block_num), addr)
print('>>> ACK')
try:
f = open('TFTPServerFIle\\Copy-'+file_name, 'wb')
except:
print('=== File "%s" no found' % file_name)
exit()
block_num += 1
while True:
recv_data, addr = sock_upload.recvfrom(1024)
opcode, block_num_recv, data = TFTPData.decode(recv_data)
print('<<< DATA')
if opcode != 3 or block_num != block_num_recv:
print('=== Error Opcode or Block Number')
# TODO: add error msg send and handle here
exit()
f.write(data)
sock_upload.sendto(TFTPAck.encode(block_num), addr)
print('>>> ACK')
if len(data) < 512:
# TODO: add transmission completed handle here
block_num = 1
print('=== File "%s" transmission completed' % file_name)
f.close()
exit()
block_num += 1 def server_run(self):
while True:
print('=== Waiting client')
msg, addr = self.server.recvfrom(1024)
print('<<< Receive a connection from client %s, msg is %s' % (addr, msg))
opcode, file_name = TFTPReadWriteRequest.decode(msg)
cmdSelect = {1: Thread(target=self.readRequest, args=(file_name, addr)),
2: Thread(target=self.writeRequest, args=(file_name, addr))}
try:
cmdSelect[opcode].start()
except:
print('<<< Receive error opcode%s' % opcode)
raise ErrorOpcode server = TFTPServer()
server.server_run()

2 TFTP 的客户端建立过程

客户端建立步骤主要有:

(1)      获取服务器ip和端口;

(2)      下载操作: 建立下载socket—发送RRQ下载请求—设置block number为1—新建文件存储下载数据—进入循环—等待接收DATA报文—确认opcode—写入数据—发送ACK报文—确认数据长度是否结束(结束则进行结束处理,并关闭文件)—block number +1;

(3)      上传操作: 建立上传socket—发送WRQ上传请求—等待ACK报文—设置block number为0—确认opcode—打开需要上传的文件—进入循环—读取数据—发送DATA报文—接收ACK报文—确认opcode—确认数据长度是否结束(结束则进行结束处理,并关闭文件)—block number +1;

 from TFTP_Helper import *
import socket class TFTPClient():
def __init__(self):
server_ip = '127.0.0.1'
port = 69
self.address = (server_ip, port) def readRequest(self, file_name):
sock_down = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
send_data = TFTPReadWriteRequest.encode('r', file_name)
sock_down.sendto(send_data, self.address)
block_num = 1
try:
f = open('TFTPClientFIle\copy-'+file_name, 'wb')
except:
print('--- File "%s" no found' % file_name)
exit()
while True:
recv_data, recv_addr = sock_down.recvfrom(1024)
print('<<< DATA', block_num)
opcode, block_num_recv, data = TFTPData.decode(recv_data)
if opcode != 3 or block_num != block_num_recv:
print('--- Opcode or Block Number Error')
# TODO: add error msg send and handle here
break
f.write(data)
sock_down.sendto(TFTPAck.encode(block_num), recv_addr)
print('>>> ACK ', block_num)
if len(data) < 512:
# TODO: add transmission completed handle here
block_num = 1
print('--- File "%s" transmission completed' % file_name)
f.close()
break
block_num += 1 def writeRequest(self, file_name):
sock_upload = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
send_data = TFTPReadWriteRequest.encode('w', file_name)
sock_upload.sendto(send_data, self.address)
print('>>> WRQ')
recv_data, addr = sock_upload.recvfrom(1024)
print('<<< ACK')
opcode, ack_block = TFTPAck.decode(recv_data)
block_num = 0
if opcode != 4 or ack_block != block_num:
print('--- Error Opcode or Block Number')
# TODO: add error msg send and handle here
exit()
try:
f = open('TFTPClientFIle\\'+file_name, 'rb')
except:
print('--- File "%s" no found' % file_name)
exit()
block_num += 1
while True:
upload_data = f.read(512)
sock_upload.sendto(TFTPData.encode(block_num, upload_data), addr)
print('>>> DATA')
ack_msg, addr = sock_upload.recvfrom(1024)
print('<<< ACK')
opcode, ack_block_num = TFTPAck.decode(ack_msg)
assert opcode == 4 and ack_block_num == block_num, 'Invalid ack message.'
if len(upload_data) < 512:
# TODO: add transmission completed handle here
block_num = 1
print('--- File "%s" transmission completed' % file_name)
f.close()
break
block_num += 1 tftp = TFTPClient()
for file in ['downFile.py', 'downFile.docx', 'downFile.txt', 'downFile.zip']:
tftp.readRequest(file)
for file in ['uploadFile.py', 'uploadFile.docx', 'uploadFile.txt', 'uploadFile.zip']:
tftp.writeRequest(file)

相关阅读


1. TFTP 的基本理论

2. struct 模块

Python的网络编程[2] -> TFTP 协议[1] -> TFTP 的 Python 实现的更多相关文章

  1. Python的网络编程[3] -> BOOTP 协议[1] -> BOOTP 的 Python 实现

    BOOTP实现 / BOOTP Implement 目录 BOOTP 的服务器建立过程 BOOTP 的客户端建立过程 Note: 理论部分请参考文末相关阅读链接 1 BOOTP 的服务器建立过程 服务 ...

  2. Python的网络编程[4] -> DHCP 协议[1] -> DHCP 的 Python 实现

    DHCP实现 / DHCP Implement 目录 DHCP 服务器建立过程 DHCP 报文加码实现过程 下面介绍建立一个简单的DHCP服务器,主要用于对基本的DHCP请求进行响应,目前只提供一个I ...

  3. Python的网络编程[4] -> DHCP 协议[0] -> DHCP 的基本理论

    DHCP协议 / DHCP Protocol 目录 DHCP 基本理论 DHCP 通信流程 DHCP 完整报文 DHCP 的 Optional 字段 DHCP 的报文类型 1 DHCP 基本理论 DH ...

  4. Python的网络编程[3] -> BOOTP 协议[0] -> BOOTP 的基本理论

    BOOTP协议 / BOOTP Protocol 目录 基本理论 BOOTP 与 DHCP 通信流程 数据报文格式 报文加解码实现 1. 基本理论 / Basic Theory BOOTP(Boots ...

  5. Python的网络编程[6] -> Modbus 协议 -> Modbus 的基本理论与 Python 实现

    Modbus协议 / Modbus Protocol 目录 Modbus 协议简介 Modbus RTU协议 Modbus TCP协议与 Python 实现 Modbus 功能码 Modbus TCP ...

  6. Python的网络编程[1] -> FTP 协议[0] -> FTP 的基本理论

    FTP协议 / FTP Protocol FTP全称为File Transfer Protocol(文件传输协议),常用于Internet上控制文件的双向传输,常用的操作有上传和下载.基于TCP/IP ...

  7. Python的网络编程[1] -> FTP 协议[2] -> 使用 ftplib 建立 FTP 客户端

    使用 ftplib 建立 FTP 客户端 用于建立FTP Client,与 pyftplib 建立的 Server 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 客户端 1. 模块信息 1 ...

  8. Python的网络编程[1] -> FTP 协议[1] -> 使用 pyftplib 建立 FTP 服务器

    使用 pyftplib 建立 FTP 服务器 pyftplib 主要用于建立 FTP Server,与 ftplib 建立的 Client 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 服 ...

  9. python之网络编程

    本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...

  10. Python高级网络编程系列之第一篇

    在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...

随机推荐

  1. 《Cracking the Coding Interview》——第14章:Java——题目1

    2014-04-26 18:20 题目:从继承的角度,把构造函数设成private有什么意义? 解法:就不能继承了.单体模式里也这么干,目的是为了不让使用者自主生成对象,进行限制. 代码: // 14 ...

  2. CocosCreator设置模拟器默认横竖屏以及机型

    之前好好的横屏,今天不知道为毛突然变成竖屏了,虽然可以在点击模拟器左上角进行设置,   但是 每次启动模拟器又变成竖屏了,折腾了很久,终于找到了设置的地方,记录下:        

  3. selenium初识(一)

    Selenium是一个开源的便携式的自动化软件测试工具,用于测试web应用程序.有能力在不同浏览器和操作系统运行.它是一套工具,帮助我们有效地给予web应用程序的自动化. Selenium分为以下几个 ...

  4. 百度webuploader上传 1

    百度webupload网址:http://fex.baidu.com/webuploader/ 引入js和css <script src="../../Content/webuploa ...

  5. 剑指offer-从尾到头打印链表03

    class Solution: # 返回从尾部到头部的列表值序列,例如[1,2,3] def printListFromTailToHead(self, listNode): # write code ...

  6. 巧用Fiddler代理来禁止资源缓存,从而达到每次都是从服务器加载最新的资源

    Fiddler ->  Rules ->  Performance  -> Disable Caching 直接设置禁用缓存,再在没有清除缓存功能的APP 中重新加载最新的页面, 每 ...

  7. React01

    目录 React-day01 入门知识 React介绍 官网 React开发环境初始化 SPA 脚手架初始化项目(方便,稳定)* 通过webpack进行初始化 配置镜像地址 开发工具配置 元素渲染 组 ...

  8. 放映PPT幻灯片演示文稿如何让演讲者备注不投影到屏幕上(转载)

    ps  files/ps.rar 放映PPT幻灯片演示文稿如何让演讲者备注不投影到屏幕上 如题,在PPT幻灯片的演示文稿中加入演讲者备注(使用PPT讲座时苦于有时会忘记一些要讲的数字,文字等),但是在 ...

  9. 使用awk根据多维度统计系统tps

    业务简单日志格式: [2017-08-28 01:00:00.523]transfer_search,7001045,1708271100083774377,20170827,,,,,,,,,,001 ...

  10. [codeforces934E]A Colourful Prospect

    [codeforces934E]A Colourful Prospect 试题描述 Firecrackers scare Nian the monster, but they're wayyyyy t ...