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

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 加解码部分

 

 1 import importlib
 2 from TFTP_Helper import *
 3 import socket
 4 from threading import Thread
 5 
 6 
 7 class TFTPServer():
 8     def __init__(self):
 9         ip = '127.0.0.1'
10         port = 69
11         address = (ip, port)
12         self.home_path = 'TFTPServerFile'
13         self.server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
14         self.server.bind(address)
15 
16     def readRequest(self, file_name, addr):
17         print('<<< RRQ', '\n=== Read request, starting file %s downing to client' % file_name, end='')
18         sock_down = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
19         block_num = 1
20         try:
21             f = open(self.home_path + '\\' + file_name, 'rb')
22         except:
23             # file no found, exit thread
24             print('=== File %s no found' % file_name)
25             exit()
26         while True:
27             down_data = f.read(512)     # data is byte format
28             sock_down.sendto(TFTPData.encode(block_num, down_data), addr)
29             print('>>> DATA', block_num)
30             ack_msg, ack_addr = sock_down.recvfrom(1024)
31             print('<<< ACK ', block_num)
32             opcode, ack_block_num = TFTPAck.decode(ack_msg)
33             assert opcode == 4 and ack_block_num == block_num, 'Invalid ack message.'
34             if len(down_data) < 512:
35                 block_num = 1
36                 print('=== Transmission of %s completed' % file_name)
37                 f.close()
38                 exit()
39             block_num += 1
40         print('=== Close file')
41         f.close()
42 
43     def writeRequest(self, file_name, addr):
44         print('<<< WRQ', '\n=== Write request, starting file %s uploading to server' % file_name)
45         sock_upload = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
46         block_num = 0
47         sock_upload.sendto(TFTPAck.encode(block_num), addr)
48         print('>>> ACK')
49         try:
50             f = open('TFTPServerFIle\\Copy-'+file_name, 'wb')
51         except:
52             print('=== File "%s" no found' % file_name)
53             exit()
54         block_num += 1
55         while True:
56             recv_data, addr = sock_upload.recvfrom(1024)
57             opcode, block_num_recv, data = TFTPData.decode(recv_data)
58             print('<<< DATA')
59             if opcode != 3 or block_num != block_num_recv:
60                 print('=== Error Opcode or Block Number')
61                 # TODO: add error msg send and handle here
62                 exit()
63             f.write(data)
64             sock_upload.sendto(TFTPAck.encode(block_num), addr)
65             print('>>> ACK')
66             if len(data) < 512:
67                 # TODO: add transmission completed handle here
68                 block_num = 1
69                 print('=== File "%s" transmission completed' % file_name)
70                 f.close()
71                 exit()
72             block_num += 1
73 
74     def server_run(self):
75         while True:
76             print('=== Waiting client')
77             msg, addr = self.server.recvfrom(1024)
78             print('<<< Receive a connection from client %s, msg is %s' % (addr, msg))
79             opcode, file_name = TFTPReadWriteRequest.decode(msg)
80             cmdSelect = {1: Thread(target=self.readRequest, args=(file_name, addr)),
81                          2: Thread(target=self.writeRequest, args=(file_name, addr))}
82             try:
83                 cmdSelect[opcode].start()
84             except:
85                 print('<<< Receive error opcode%s' % opcode)
86                 raise ErrorOpcode
87 
88 server = TFTPServer()
89 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;

 1 from TFTP_Helper import *
 2 import socket
 3 
 4 
 5 class TFTPClient():
 6     def __init__(self):
 7         server_ip = '127.0.0.1'
 8         port = 69
 9         self.address = (server_ip, port)
10 
11     def readRequest(self, file_name):
12         sock_down = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
13         send_data = TFTPReadWriteRequest.encode('r', file_name)
14         sock_down.sendto(send_data, self.address)
15         block_num = 1
16         try:
17             f = open('TFTPClientFIle\copy-'+file_name, 'wb')
18         except:
19             print('--- File "%s" no found' % file_name)
20             exit()
21         while True:
22             recv_data, recv_addr = sock_down.recvfrom(1024)
23             print('<<< DATA', block_num)
24             opcode, block_num_recv, data = TFTPData.decode(recv_data)
25             if opcode != 3 or block_num != block_num_recv:
26                 print('--- Opcode or Block Number Error')
27                 # TODO: add error msg send and handle here
28                 break
29             f.write(data)
30             sock_down.sendto(TFTPAck.encode(block_num), recv_addr)
31             print('>>> ACK ', block_num)
32             if len(data) < 512:
33                 # TODO: add transmission completed handle here
34                 block_num = 1
35                 print('--- File "%s" transmission completed' % file_name)
36                 f.close()
37                 break
38             block_num += 1
39 
40     def writeRequest(self, file_name):
41         sock_upload = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
42         send_data = TFTPReadWriteRequest.encode('w', file_name)
43         sock_upload.sendto(send_data, self.address)
44         print('>>> WRQ')
45         recv_data, addr = sock_upload.recvfrom(1024)
46         print('<<< ACK')
47         opcode, ack_block = TFTPAck.decode(recv_data)
48         block_num = 0
49         if opcode != 4 or ack_block != block_num:
50             print('--- Error Opcode or Block Number')
51             # TODO: add error msg send and handle here
52             exit()
53         try:
54             f = open('TFTPClientFIle\\'+file_name, 'rb')
55         except:
56             print('--- File "%s" no found' % file_name)
57             exit()
58         block_num += 1
59         while True:
60             upload_data = f.read(512)
61             sock_upload.sendto(TFTPData.encode(block_num, upload_data), addr)
62             print('>>> DATA')
63             ack_msg, addr = sock_upload.recvfrom(1024)
64             print('<<< ACK')
65             opcode, ack_block_num = TFTPAck.decode(ack_msg)
66             assert opcode == 4 and ack_block_num == block_num, 'Invalid ack message.'
67             if len(upload_data) < 512:
68                 # TODO: add transmission completed handle here
69                 block_num = 1
70                 print('--- File "%s" transmission completed' % file_name)
71                 f.close()
72                 break
73             block_num += 1
74 
75 
76 tftp = TFTPClient()
77 for file in ['downFile.py', 'downFile.docx', 'downFile.txt', 'downFile.zip']:
78     tftp.readRequest(file)
79 for file in ['uploadFile.py', 'uploadFile.docx', 'uploadFile.txt', 'uploadFile.zip']:
80     tftp.writeRequest(file)


相关阅读


1. TFTP 的基本理论

2. struct 模块

posted @ 2017-12-30 12:58  StackLike  阅读(1461)  评论(0编辑  收藏  举报