本文实例为大家分享了python实现简单tftp的具体代码,供大家参考,具体内容如下
- tftp是基于udp的协议
- 实现简单的tftp,首先要有tftp的协议图。
- tftp默认接收端口为69,但每次有连接过来后,tftp会随机分配一个端口来专门为这个连接来服务。
- 操作码:1.上传 2.下载 3.传数据 4.接收确认 5.错误码
tftp服务器简单实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
from threading import Thread from socket import * import struct def upload(filename,user_ip,user_port): num = 0 f = open (filename, 'ab' ) s_up = socket(AF_INET,SOCK_DGRAM) send_data_1 = struct.pack( "!HH" , 4 ,num) s_up.sendto(send_data_1,(user_ip,user_port)) #第一次用随机端口发送 while True : recv_data,user_info = s_up.recvfrom( 1024 ) #第二次客户连接我随机端口 caozuohao_up,ack_num = struct.unpack( '!HH' ,recv_data[: 4 ]) print (caozuohao_up,ack_num,num) if int (caozuohao_up) = = 3 and ack_num = = num : f.write(recv_data[ 4 :]) send_data = struct.pack( "!HH" , 4 ,num) s_up.sendto(send_data,(user_ip,user_port)) #第二次我用随机端口发 num = num + 1 if len (recv_data) < 516 : print (user_ip + '上传文件' + filename + ':完成' ) f.close() exit() def download(filename,user_ip,user_port): s_down = socket(AF_INET, SOCK_DGRAM) num = 0 try : f = open (filename, 'rb' ) except : error_data = struct.pack( '!HHHb' , 5 , 5 , 5 ,num) s_down.sendto(error_data, (user_ip,user_port)) #文件不存在时发送 exit() #只会退出此线程 while True : read_data = f.read( 512 ) send_data = struct.pack( '!HH' , 3 ,num) + read_data s_down.sendto(send_data, (user_ip,user_port)) #数据第一次发送 if len (read_data) < 512 : print ( '传输完成, 对方下载成功' ) exit() recv_ack = s_down.recv( 1024 ) #第二次接收 caozuoma,ack_num = struct.unpack( "!HH" , recv_ack) # print(caozuoma,ack_num,len(read_data)) num + = 1 if int (caozuoma) ! = 4 or int (ack_num) ! = num - 1 : exit() f.close() s = socket(AF_INET,SOCK_DGRAM) s.bind(('', 69 )) def main(): while 1 : recv_data,(user_ip,user_port) = s.recvfrom( 1024 ) #第一次客户连接69端口 print (recv_data, user_ip, user_port) if struct.unpack( '!b5sb' ,recv_data[ - 7 :]) = = ( 0 , b 'octet' , 0 ): caozuoma = struct.unpack( '!H' ,recv_data[: 2 ]) filename = recv_data[ 2 : - 7 ].decode( 'gb2312' ) if caozuoma[ 0 ] = = 1 : print ( '对方想下载数据' ,filename) t = Thread(target = download, args = (filename,user_ip,user_port)) t.start() elif caozuoma[ 0 ] = = 2 : print ( '对方想上传数据' ,filename) t = Thread(target = upload, args = (filename,user_ip,user_port)) t.start() if __name__ = = '__main__' : main() |
上传数据简单实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#!/usr/bin/env python3 #coding=utf-8 import struct from socket import * server_ip = '192.168.119.157' send_data_1 = struct.pack( '!H8sb5sb' , 2 , '王辉.jpg' .encode( 'gb2312' ), 0 ,b 'octet' , 0 ) s = socket(AF_INET,SOCK_DGRAM) s.sendto(send_data_1,(server_ip, 69 )) #第一次发给服务器69端口 f = open ( '王辉.jpg' , 'rb' ) recv_data = s.recvfrom( 1024 ) #第一次接收数据 rand_port = recv_data[ 1 ][ 1 ] print () ack_num = struct.unpack( "!HH" ,recv_data[ 0 ][: 4 ]) num = 0 while True : read_data = f.read( 512 ) send_data = struct.pack( '!HH' , 3 ,num) + read_data s.sendto(send_data,(server_ip,rand_port)) #第二次发给服务器的随机端口 recv_data_2,userinfo = s.recvfrom( 1024 ) print (recv_data_2) ack_num = struct.unpack( '!H' ,recv_data_2[ 2 : 4 ]) print ( len (read_data),num,ack_num[ 0 ],rand_port) if len (read_data) < 512 or ack_num[ 0 ] ! = num : break num = num + 1 |
下载数据简单实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#!/usr/bin/env python3 #coding=utf-8 import struct from socket import * filename = 'test.jpg' server_ip = '192.168.1.113' send_data = struct.pack( '!H%dsb5sb' % len (filename), 1 ,filename.encode( 'gb2312' ), 0 , 'octet' .encode( 'gb2312' ), 0 ) s = socket(AF_INET,SOCK_DGRAM) s.sendto(send_data,(server_ip, 69 )) #第一次发送, 连接服务器69端口 f = open (filename, 'ab' ) while 1 : recv_data = s.recvfrom( 1024 ) #接收数据 caozuoma,ack_num = struct.unpack( '!HH' ,recv_data[ 0 ][: 4 ]) #获取数据块编号 rand_port = recv_data[ 1 ][ 1 ] #获取服务器的随机端口 if int (caozuoma) = = 5 : print ( '服务器返回: 文件不存在...' ) break print (caozuoma,ack_num,rand_port, len (recv_data[ 0 ])) f.write(recv_data[ 0 ][ 4 :]) if len (recv_data[ 0 ]) < 516 : break ack_data = struct.pack( "!HH" , 4 ,ack_num) s.sendto(ack_data,(server_ip,rand_port)) #回复ACK确认包 |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/Erick-L/p/7144139.html