tftp协议、下载和发送数据到服务器、

TFTP(Trivial File Transfer Protocol ,简单文件传输协议):

1、tftp32.exe运行起来当做一个共享服务器

C/S  client/server :需要一个单独的客户端   B/S  browser/server :浏览器与服务器,不需要客户端


udpSocket.recvfrom(1024) ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接:有可能是因为接受数据的服务器已经关闭,没有接收成功。


多个字节的数据在网络中以大端形式存取:高位存在了低地址 0x1122 :低地址存放高位11,。

import struct

cmd=struct.pack("!H8sb5sb",1,"1.jpg",0,"octet",0) 其中:!代表网络中存放大端形式;H表示占两个字节; s占一个字节,8s占8个字节;b占一个字节,5s占5个字节;b占一个字节

cmdTuple=struct.unpack("!HH",recvData[:4]) //对收到的4个字节数据进行处理  !表示数据由网络中得到,H表示两个字节、两个字节分别进行处理


套接字不使用使将其关掉,udpSocket.close()

2、从tftp服务器上下载文件:

服务器的69端口只接受下载请求,确认包都要在随机端口中确认。

需要满足tftp协议

a、创建一个空文件

b、向文件中写入数据

c、关闭

向服务器上上传文件:

f=open("1.jpg",'bw') //加上b,代表二进制形式


把数据发送给别人,自己就是服务器;别人要发送数据,别人就是服务器; 服务器----发送数据

tftp协议、下载和发送数据到服务器、_第1张图片

tftp协议、下载和发送数据到服务器、_第2张图片

过程:

TFTP服务器默认监听69号端口

当客户端发送“下载”请求(即读请求)时,需要向服务器的69端口发送

服务器若批准此请求,则使用一个新的、临时的 端口进行数据传输

当服务器找到需要现在的文件后,会立刻打开文件,把文件中的数据通过TFTP协议发送给客户端

如果文件的总大小较大(比如3M),那么服务器分多次发送,每次会从文件中读取512个字节的数据发送过来

因为发送的次数有可能会很多,所以为了让客户端对接收到的数据进行排序,所以在服务器发送那512个字节数据的时候,会多发2个字节的数据,用来存放序号,并且放在512个字节数据的前面,序号是从1开始的

因为需要从服务器上下载文件时,文件可能不存在,那么此时服务器就会发送一个错误的信息过来,为了区分服务发送的是文件内容还是错误的提示信息,所以又用了2个字节 来表示这个数据包的功能(称为操作码),并且在序号的前面

操作码 功能
1 读请求,即下载
2 写请求,即上传
3 表示数据包,即DATA
4 确认码,即ACK
5 错误

因为udp的数据包不安全,即发送方发送是否成功不能确定,所以TFTP协议中规定,为了让服务器知道客户端已经接收到了刚刚发送的那个数据包,所以当客户端接收到一个数据包的时候需要向服务器进行发送确认信息,即发送收到了,这样的包成为ACK(应答包)

为了标记数据已经发送完毕,所以规定,当客户端接收到的数据小于516(2字节操作码+2个字节的序号+512字节数据)时,就意味着服务器发送完毕了


3、根据上面的协议编写代码,从服务上下载文件

#coding:utf-8
from socket import * 
import struct
import sys
reload(sys)  
#sys.setdefaultencoding('utf-8')
sys.setdefaultencoding('utf-8')  


def main():
	sendData=struct.pack("!H10sb5sb",1,"saber2.png",0,"octet",0)
	
	udpSocket=socket(AF_INET,SOCK_DGRAM)
	#udpSocket.sendto(sendData,("127.0.0.1",69))
	#udpSocket.sendto(sendData,("192.168.59.1",69))
	udpSocket.sendto(sendData.encode("gb2312"),("192.168.80.70",69))
	
	recvFile=""
	packNum=0
	while True:
		recvInfo,recvAddr=udpSocket.recvfrom(1024)
		recvLen=len(recvInfo)
		resultTuple=struct.unpack("!HH",recvInfo[:4])
		#按照上传的方式转为一个字节,result为元组形式
		cmd=resultTuple[0]
		currentPackNum=resultTuple[1]
		if cmd==3:
			if currentPackNum==1:
				recvFile=open("new.png","a")

			if packNum+1==currentPackNum:
				recvFile.write(recvInfo[4:])
				packNum+=1
				print("%d 次接收到的数据"%(packNum))
				ackBuf=struct.pack("!HH",4,packNum)
				udpSocket.sendto(ackBuf.encode("gb2312"),recvAddr)

			if recvLen<516:
				recvFile.close()
				print("下载成功")
				break

		elif cmd==5:
			print("error")
			break
	udpSocket.close()


if __name__=="__main__":
	print(sys.getdefaultencoding())#utf-8
	print(sys.stdin.encoding)	#utf-8
	print(sys.stdout.encoding) #utf-8
	main()
		


但是显示的数据不正确;

utf-8
utf-8
utf-8
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
8 次接收到的数据
[Decode error - output not utf-8]
[Decode error - output not utf-8]
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 次接收到的数据
73 次接收到的数据
74 次接收到的数据
75 次接收到的数据
76 次接收到的数据
77 次接收到的数据
78 次接收到的数据
79 次接收到的数据
80 次接收到的数据
81 次接收到的数据
82 次接收到的数据
83 次接收到的数据
84 次接收到的数据
85 次接收到的数据
86 次接收到的数据
87 次接收到的数据
88 次接收到的数据
89 次接收到的数据
90 次接收到的数据
91 次接收到的数据
92 次接收到的数据
93 次接收到的数据
94 次接收到的数据
95 次接收到的数据
96 次接收到的数据
97 次接收到的数据
98 次接收到的数据
99 次接收到的数据
100 次接收到的数据
101 次接收到的数据
102 次接收到的数据
103 次接收到的数据
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
113 次接收到的数据
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
119 次接收到的数据
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
124 次接收到的数据
125 次接收到的数据
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
[Decode error - output not utf-8]
下载成功
[Finished in 0.5s]


将python2换为python3后解决问题,“wb+”得到的数据为正确的。

4、python3中有一些改变,比如:没有reload,byte前加b

#coding:utf-8  
from socket import *   
import struct  
import sys  
   
def main():  
    sendData=struct.pack("!H10sb5sb",1,b"saber2.png",0,b"octet",0) 
      
    udpSocket=socket(AF_INET,SOCK_DGRAM)  
    #udpSocket.sendto(sendData,("127.0.0.1",69))  
    #udpSocket.sendto(sendData,("192.168.59.1",69))  
    udpSocket.sendto(sendData,("192.168.80.70",69))  
      
    recvFile=""  
    packNum=0  
    while True:  
        recvInfo,recvAddr=udpSocket.recvfrom(1024)  
        recvLen=len(recvInfo)  
        resultTuple=struct.unpack("!HH",recvInfo[:4])  
        #按照上传的方式转为一个字节,result为元组形式  
        cmd=resultTuple[0]  
        currentPackNum=resultTuple[1]  
        if cmd==3:  
            if currentPackNum==1:  
                recvFile=open("new2.png","wb+")  
  
            if packNum+1==currentPackNum:  
                recvFile.write(recvInfo[4:])  
                packNum+=1  
                print("%d 次接收到的数据"%(packNum))  
                ackBuf=struct.pack("!HH",4,packNum)  
                udpSocket.sendto(ackBuf,recvAddr)  
  
            if recvLen<516:  
                recvFile.close()  
                print("下载成功")  
                break  
  
        elif cmd==5:  
            print("error")  
            break  
    udpSocket.close()  
  
  
if __name__=="__main__":      
    print(sys.stdin.encoding)   #utf-8  
    print(sys.stdout.encoding) #utf-8  
    main() 

 
  

。。


你可能感兴趣的:(python)