Python的网络编程[2] -> TFTP 协议[1] -> TFTP 的 Python 实现
TFTP实现 / TFTP Implement
目录
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 实现的更多相关文章
- Python的网络编程[3] -> BOOTP 协议[1] -> BOOTP 的 Python 实现
BOOTP实现 / BOOTP Implement 目录 BOOTP 的服务器建立过程 BOOTP 的客户端建立过程 Note: 理论部分请参考文末相关阅读链接 1 BOOTP 的服务器建立过程 服务 ...
- Python的网络编程[4] -> DHCP 协议[1] -> DHCP 的 Python 实现
DHCP实现 / DHCP Implement 目录 DHCP 服务器建立过程 DHCP 报文加码实现过程 下面介绍建立一个简单的DHCP服务器,主要用于对基本的DHCP请求进行响应,目前只提供一个I ...
- Python的网络编程[4] -> DHCP 协议[0] -> DHCP 的基本理论
DHCP协议 / DHCP Protocol 目录 DHCP 基本理论 DHCP 通信流程 DHCP 完整报文 DHCP 的 Optional 字段 DHCP 的报文类型 1 DHCP 基本理论 DH ...
- Python的网络编程[3] -> BOOTP 协议[0] -> BOOTP 的基本理论
BOOTP协议 / BOOTP Protocol 目录 基本理论 BOOTP 与 DHCP 通信流程 数据报文格式 报文加解码实现 1. 基本理论 / Basic Theory BOOTP(Boots ...
- Python的网络编程[6] -> Modbus 协议 -> Modbus 的基本理论与 Python 实现
Modbus协议 / Modbus Protocol 目录 Modbus 协议简介 Modbus RTU协议 Modbus TCP协议与 Python 实现 Modbus 功能码 Modbus TCP ...
- Python的网络编程[1] -> FTP 协议[0] -> FTP 的基本理论
FTP协议 / FTP Protocol FTP全称为File Transfer Protocol(文件传输协议),常用于Internet上控制文件的双向传输,常用的操作有上传和下载.基于TCP/IP ...
- Python的网络编程[1] -> FTP 协议[2] -> 使用 ftplib 建立 FTP 客户端
使用 ftplib 建立 FTP 客户端 用于建立FTP Client,与 pyftplib 建立的 Server 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 客户端 1. 模块信息 1 ...
- Python的网络编程[1] -> FTP 协议[1] -> 使用 pyftplib 建立 FTP 服务器
使用 pyftplib 建立 FTP 服务器 pyftplib 主要用于建立 FTP Server,与 ftplib 建立的 Client 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 服 ...
- python之网络编程
本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...
- Python高级网络编程系列之第一篇
在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...
随机推荐
- 剑指Offer - 九度1391 - 顺时针打印矩阵
剑指Offer - 九度1391 - 顺时针打印矩阵2013-11-24 04:55 题目描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 ...
- Vbs 测试程序二
这是一段原载于百度百科上的代码,Chaobs转载 原帖已删,就是怕有人用这个恶意程序. 慎用! dim folder,fso,foldername,f,d,dc set fso=createobjec ...
- Git上手:四种常见的Git协同工作方式
1.集中式工作流 适用人群:开发小团队(4-5人),习惯使用SVN工具的小团队. 工作方式:团队组长创建远程仓库,创建一个master分支,组员可读可写. 每个开发人员都git clone远程仓库到本 ...
- BigDecimal简单说
1) 浮点数的舍弃规则: 假设小数点后保留两位 RoundingMode.CEILING:向正无穷大的方向舍入: 1.245 → 1.25 -1.245 → -1.24 RoundingMode ...
- ironic的自动化脚本
# -*- coding:utf-8 -*- import json import subprocess import os import time import random trunk_start ...
- tomcat启动后服务访问404
. 解决办法: 在tomcat文件中有个work文件夹.其中,tomcat属于admin用户,work属于 admin用户 ,启动服务由admin用户启动. 但是发现work文件下的目录权限属于 ...
- beta版本前准备
目录 过去存在的问题 任务分工 开发规范 后端总结 卉卉 家灿 前端总结 绪佩 青元 恺琳 宇恒 丹丹 算法&API接口 家伟 鸿杰 一好 文档&博客撰写 政演 产品功能 我们已经做了 ...
- js动态生成下拉列表
经常需要用到js动态生成下拉列表的功能,记录下来备用. 示例需求:通过ajax请求,从后台获取用户姓名列表,并添加到下拉列表中.js代码如下: function getNameList(){ //如果 ...
- 二、vue响应式对象
Object.defineProperty Object.defineProperty 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象,先来看一下它的语法: Obj ...
- 【bzoj2306】[Ctsc2011]幸福路径 倍增Floyd
题目描述 一张n个点的有向图,每个点有一个权值.一开始从点$v_0$出发沿图中的边任意移动,移动到路径上的第$i$个点 输入 每一行中两个数之间用一个空格隔开. 输入文件第一行包含两个正整数 n, ...