Python用socket实现ftp上传下载文件

Python用socket实现ftp上传下载文件

FTP是什么?

FTP就是文件传输协议。用于互联网双向传输,控制文件下载空间在服务器复制文件从本地计算机或本地上传文件复制到服务器上的空间。

socket实现简单的下载文件

ftp_server.py
import socket,os,hashlib
server=socket.socket()
server.bind(('localhost',9999))
server.listen(5)
print('我准备开始等电话了')
while True:
    conn,addr=server.accept()
    print('电话来了',conn)
    while True:
        try:
            data=conn.recv(1024)
            cmd,filename=data.decode().split() #按照空格分割字符,第二个值为文件名字
            print(filename)
            if os.path.isfile(filename): #判断是否存在当前的文件
                f=open(filename,'rb')
                m=hashlib.md5() #生成一个md5对象
                file_size=os.stat(filename).st_size #stat返回的内容中包含文件大小,直接提取出来
                conn.send(str(file_size).encode()) #发送给客户端
                conn.recv(1024) #等待客户端确认
                for line in f:
                    m.update(line)#对文件进行加密
                    conn.send(line) #发送文件给客户端接受
                print('文件md5值:',m.hexdigest())
                f.close()
                conn.send(m.hexdigest().encode()) #发送md5值个客户端
        except ConnectionResetError as e: #防止当前客户端断开,服务器端直接断掉
            print(addr,'当前客户端已经断开连接了')
            break
server.close()
ftp_client.py
import socket,hashlib

client = socket.socket()
client.connect(('localhost', 9999))
while True:
    input_content=input('请输入需要下载的文件:').strip() #前后的空格去掉
    if len(input_content)==0:continue #输入为空则继续输入
    if input_content.startswith("get"): #判断输入内容是否以get开始--> get 文件名字
        client.send(input_content.encode()) #
        file_size=client.recv(1024) #接受服务器端返回的文件大小
        print('文件大小为:',file_size.decode())
        client.send('准备好开始发送文件了'.encode()) #确认发送
        receive_size=0 #生成一个空值
        file_name=input_content.strip()[4:] #我们提取get 后面的内容作为新的文件名字
        f=open(file_name+"_new.py",'wb') #打开新的文件
        m=hashlib.md5() #生成一个加密对象
        
        while receive_size &lt int(file_size.decode()): #空值小于原文件大小的话,就一直接收
            data=client.recv(1024)
            receive_size+=len(data)
            m.update(data) #md5加密
            f.write(data) #写入收到了内容
        else:
            file_md5=m.hexdigest()
            print('文件传输完毕,md5值为:',file_md5) #打印md5值
            f.close()
        server_file_md5=client.recv(1024)
        print('服务器端的md5值为:',server_file_md5.decode()) #跟服务器端的md5值比较
client.close()

上面的代码就简单的实现了向服务器端下载文件的操作,并且还加入了md5加密。我们可以看到在服务器端有两次send连在了一起,那么在Linux上就会引起粘包,在Windows上测试好像没什么问题。我们可以在两个send的中间在插入一次交互,就是客户端确认,服务器端接收确认信息,之后在发送也是可以的,但是多次交互就会导致程序变慢,何况我们加入了md5加密,会更加慢,说到底我们可以在客户端进行修改:

import socket,hashlib

client = socket.socket()
client.connect(('localhost', 9999))
while True:
    input_content=input('请输入需要下载的文件:').strip() #前后的空格去掉
    if len(input_content)==0:continue #输入为空则继续输入
    if input_content.startswith("get"): #判断输入内容是否以get开始--> get 文件名字
        client.send(input_content.encode()) #
        file_size=client.recv(1024) #接受服务器端返回的文件大小
        print('文件大小为:',file_size.decode())
        client.send('准备好开始发送文件了'.encode()) #确认发送
        receive_size=0 #生成一个空值
        file_name=input_content.strip()[4:] #我们提取get 后面的内容作为新的文件名字
        f=open(file_name+"_new.py",'wb') #打开新的文件
        m=hashlib.md5() #生成一个加密对象
        while receive_size < int(file_size.decode()):  #这样判断,只有最后一次才会超过
            if  int(file_size.decode())-receive_size > 1024:  #只要大于1024就一直收
                size=1024
            else:  #小于1024的话,我们就收剩下的
                size=int(file_size.decode())-receive_size
                print('接受文件大小为:', size)
            data=client.recv(size)
            receive_size+=len(data)
            m.update(data) #md5加密
            f.write(data) #写入收到了内容
        else:
            file_md5=m.hexdigest()
            print('文件传输完毕,md5值为:',file_md5) #打印md5值
            f.close()
        server_file_md5=client.recv(1024)
        print('服务器端的md5值为:',server_file_md5.decode()) #跟服务器端的md5值比较
client.close()
分享到 :

发表评论

登录... 后才能评论