python socket基础二模拟 FTP处理文件

解析代码的思路:

首先,先将服务器和客户端的建立连接,连接成功后,客户端要先将自己的请求发送至server,因为ftp的get是处理文件的,所以采用cmd.startwith('get')作为判断条件,这个时候必须收到server的应答,server_response,表示server已经准备可以接受数据了,这个时候client就将数据发送过去,然后server接收,注意只要server发或者收,同样的client也必须收或者发,不然由于采用accept是阻塞型的,只有收到recv才会继续进行下去,这与FTP协议是一致的.

#client
import socket
import hashlib
client = socket.socket()
client.connect(('localhost',9999))
while True:
        cmd = input(">>: ").strip()
        if len(cmd) == 0:continue
        if cmd.startswith("get"):
                client.send(cmd.encode())
                server_response = client.recv(1024)
                print("server response: ",server_response)
                client.send(b"ready to recv file")
                file_total_size = int(server_response.decode())
                received_size = 0
                filename = cmd.split()[1]
                f = open(filename + ".new","wb")
                m = hashlib.md5()

                while received_size < file_total_size:
                        if file_total_size - received_size > 1024:
                                size = 1024
                        else:
                                size = file_total_size -received_size
                                print("last received:",size)

                        data = client.recv(size)
                        received_size += len(data)
                        m.update(data)
                        f.write(data)
                else:
                        new_file_md5 = m.hexdigest()
                        print("file recv done",received_size,file_total_size)
                        f.close()
                server_file_md5 = client.recv(1024)
                print("server file md5: ",server_file_md5)
                print("client file md5: ",new_file_md5)
client.close()
#server
import socket,os
import hashlib
server = socket.socket()
server.bind(('0.0.0.0',9999))
server.listen(5)
print("等待连接....")
while True:
        conn,addr = server.accept()
        print("连接成功....")
        while True:
                print("等待指令")
                data = conn.recv(1024)
                if not data:
                        print("客户端已断开")
                        break
                cmd,filename = data.decode().split()
                print(filename)
                if os.path.isfile(filename):
                        f = open(filename,"rb")
                        m = hashlib.md5()
                        file_size = os.stat(filename).st_size
                        conn.send( str(file_size).encode() )
                        conn.recv(1024)#wait for ask
                        for line in f:
                                m.update(line)
                                conn.send(line)
                        print("file md5",m.hexdigest())
                        f.close()
                        conn.send(m.hexdigest().encode())
                print("文件发送完毕....")
server.close()

其中

Ftp server读取文件名,检测文件是否存在os.path.isfile(filename)
打开文件open()检测文件大小 received_size和file_total_size比较防止粘包,
发送文件大小给客户端,等客户端确认大小,然后开始边读边发数据发送md5 
客户端的md5与服务器端的md5对比,相同即文件传输过程没有改变
MD5的使用过程
import hashlib
MD5=hashlib.md5()
MD5.update(r'str')
MD5.hexdigest()
要是send的话需要将文件的内容decode,encode默认是utf-8

猜你喜欢

转载自blog.csdn.net/qq_37312720/article/details/82963290