tftp服务起下载文件 from socket import *
import struct
import os
import sys
def main():
if len(sys.argv) != 3:
print("请按照规则运行程序:python3 xxx.py ip filename")
exit()
#服务器ip
tftp_ip = sys.argv[1]
#文件名字
file_name = sys.argv[2]
#名字大小
file_num = len(file_name)
#下载请求
cmd_buf = struct.pack("!H%dsb5sb"%file_num,1,file_name.encode("utf-8"),0,"octet".encode("utf-8"),0)
#创建套接字
socket_udp = socket(AF_INET,SOCK_DGRAM)
#给服务器发送我需要的东西
socket_udp.sendto(cmd_buf,(tftp_ip,69))
#打开一个文件
f = open(file_name,"bw")
flag = True
num = 0
while True:
result = socket_udp.recvfrom(1024)
#数据 新ip端口
tftp_data,tftp_ip_port = result
#操作号
cmd_tuple = struct.unpack("!H",tftp_data[:2])
#块编号
cmd_tuple2 = struct.unpack("!H",tftp_data[2:4])
#操作码
tftp_opcode = cmd_tuple[0]
#块编号
tftp_serial_number = cmd_tuple2[0]
#打印当前快编号
print(tftp_serial_number)
if tftp_opcode == 3: #是否为数据
#计算出这次应该接收到的文件的序号值,应该是上一次接收到的值的基础上+1
num = num + 1
# 如果一个下载的文件特别大,即接收到的数据包编号超过了2个字节的大小
# 那么会从0继续开始,所以这里需要判断,如果超过了65535 那么就改为0
if num == 65536:
num = 0
if num == tftp_serial_number: # 用块编号测试是否有重复数据
f.write(tftp_data[4:])
#测试Ack
cmd_buf2 = struct.pack("!HH",4,tftp_serial_number)
#把当前接收到的 快编号发送个服务器 随机端口和ip
socket_udp.sendto(cmd_buf2,tftp_ip_port)
#测试数据长度
if len(tftp_data) < 516:
print("传输完毕.....")
break
elif tftp_opcode == 5:
print("没有这个文件夹......")
flag = Falsh
if flag == True:
f.close() #关闭文件
else:
os.unlink(file_name)#没有这个文件 把创建的文件删除
socket_udp.close() #关闭套接字
if __name__ == "__main__":
main()
tftp服务器上传文件 from socket import *
import struct
import sys
import os
#上传的主要核心你要知道你是发送方
#服务器是接收方 服务器反回确认信息,或者报错信息
def main():
if len(sys.argv) != 3:
print("python3 xxx.py ip filename")
exit()
tftpd_ip = sys.argv[1]
tftpd_file_name = sys.argv[2]
#打包
cmd_buf = struct.pack("!H%dsb5sb"%len(tftpd_file_name),2,tftpd_file_name.encode("utf-8"),0,"octet".encode("utf-8"),0)
socket_udp = socket(AF_INET,SOCK_DGRAM)
socket_udp.sendto(cmd_buf,(tftpd_ip,69))
f = open(tftpd_file_name,"br")
num = 1 #这里写1是因为 我上面发送了一次的
flag = True
while True:
result = socket_udp.recvfrom(1024)
#服务起反回的确认信息 和 ip port
tftpd_data,tftpd_ip_port = result
#操作号 服务的确认的操作好
op_num = struct.unpack("!H",tftpd_data[:2])
#块编号 服务起反回的快编号
pack_num = struct.unpack("!H",tftpd_data[2:4])
print(pack_num[0])
if op_num[0] == 4:
if num-1 == pack_num[0]: # 这里写num-1 是因为 pack_num[0] 是反回的我上次发的快编号
send_data = f.read(512)
if len(send_data) < 512:
print("传输完成........")
break
#num是快编号 因为我是发送方 我要自做个快比那好
cmd_bug = struct.pack("!HH%ds"%len(send_data),3,num,send_data) #send_data是读取的文件信息
socket_udp.sendto(cmd_bug,tftpd_ip_port) #发给服务器
num = num + 1 #我的快编号加1
elif op_num[0] == 5:
print("没有这个文件......")
flag = Falsh
break
if flag == True:
f.close()
else:
os.unlink(tftpd_file_name) #删除这个文件
if __name__ == "__main__":
main()