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四次握 ...
随机推荐
- 《数据结构与算法分析:C语言描述》复习——第五章“堆”——二叉堆
2014.06.15 22:14 简介: 堆是一种非常实用的数据结构,其中以二叉堆最为常用.二叉堆可以看作一棵完全二叉树,每个节点的键值都大于(小于)其子节点,但左右孩子之间不需要有序.我们关心的通常 ...
- 剑指Offer - 九度1515 - 打印1到最大的N位数
剑指Offer - 九度1515 - 打印1到最大的N位数2013-11-30 01:11 题目描述: 给定一个数字N,打印从1到最大的N位数. 输入: 每个输入文件仅包含一组测试样例.对于每个测试案 ...
- 《Cracking the Coding Interview》——第5章:位操作——题目4
2014-03-19 06:15 题目:解释(n & (n - 1)) == 0是什么意思? 解法:n&n-1是去掉最低位‘1’的方法.根据运算符优先级,貌似用不着加那个括号,但位运算 ...
- springboot10 framwork
一.Spring介绍 Spring 是位于业务逻辑层的框架. 优点很多(无缝对接前后层的框架.提供AOP的支持 , 和以前的 Sstruts . Hibernate 组合成了一套框架组合 SSH .现 ...
- poj 1459 网络流问题`EK
Power Network Time Limit: 2000MS Memory Limit: 32768K Total Submissions: 24930 Accepted: 12986 D ...
- 细说php2[正则表达式学习笔记]
<细说php>这本书应该是每个php程序员入门的必读书籍,里面讲的很多知识都很系统和详细,看了正则这部分,并练习了里面的案例,发现自己已经会了很多.... header('Content- ...
- Android使用adb命令查看CPU信息
Android中使用JNI编程的时候会需要编译出不同的SO文件,以供适配不同的机型. 例如: 由此需要查看不同机型的CPU信息. 使用ADB命令查看CPU信息命令如下: 1. adb shell 2. ...
- 2013 ACMICPC 杭州现场赛 I题
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #in ...
- TCP面试题之三次握手过程
TCP简介: 1.面向连接的.可靠的.基于字节流的传输层的通信协议: 2.将应用层的数据流分割成报文段并发送给目标节点的TCP层: 3.数据包都有序号,对方收到则发送ACK确认,未收到则重传: 4.使 ...
- css 实现高斯模糊
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...