用python写一个简单的TFTP服务器
用python写一个简单的TFTP服务器,练习python socket用法。 暂时只实现文件上传,思路很简单: 1.创建UDP接口; 2.监听69端口; 3.接收UDP数据; 4.解析TFTP协议报文,执行创建文件或写入文件;
#!python
#Simple TFTP Server
#蒋晓岗<kerndev@foxmail.com>
import os
import io
import sys
import time
import socket
def send_ack(s, addr, pid):
pkt = b"\x00\x04" + pid
s.sendto(pkt, addr)
def send_err(s, addr, code, reason):
pkt = b"\x00\x05" + code.to_bytes(2, "big") + reason.encode("utf-8") + b"\x00"
s.sendto(pkt, addr)
#print(pkt.hex(" "))
#main
total = 0
processing = False
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("0.0.0.0",69))
s.settimeout(2)
print("TFTPD start...")
while(True):
try:
req = s.recvfrom(1024)
except Exception as e:
if(processing):
processing = False
fp.close()
print("\nRecv file failed:", e)
else:
req_data = req[0]
req_addr = req[1]
#print("recv", len(req_data), "bytes from:", req_addr)
if(req_data[0:2] == b"\x00\x02"):
name = req_data[2:].split(b"\x00")[0].decode("utf-8")
if(processing):
print("\nRefused new file:", name, ", from:", req_addr)
send_err(s, req_addr, 0x00, "server busy!")
else:
try:
fp = open(name, "wb+")
except Exception as e:
print("Accept new file:", name, ", from:", req_addr, "failed!", e)
send_err(s, req_addr, 0x03, "disk error!")
else:
print("Accept new file:", name, ", from:", req_addr, "OK")
send_ack(s, req_addr, b"\x00\x00")
processing = True
total = 0
if(req_data[0:2] == b"\x00\x03"):
if not processing:
send_err(s, req_addr, 0x04, "invalid session!")
else:
pid = req_data[2:4]
buf = req_data[4:]
total = total + len(buf)
fp.write(buf)
send_ack(s, req_addr, pid)
print("Recv %d bytes" % total, end="\r")
if(len(buf) < 512):
processing = False
fp.close()
print("\nRecv file complete, total size:", total, "bytes")
使用Windows自带TFTP进行上传文件的测试。

程序运行结果:
