• day8--socket文件传输


    FTP server

    1、读取文件名

    2、检测文件是否存在

    3、打开文件

    4、检测文件大小(告诉客户端发送文件的大小)

    5、发送文件大小和MD5值给客户端,MD5

    6、等待客户端确认(防止粘包)

    7、开始边读边发数据

    8、发送完整的MD5

    9、关闭服务器

    socket收发文件,服务器端打开并发送文件,客户端接收并存储文件;这样就能实现文件的传输功能。

    os模块中的os.path.isfile()和os.path.exists():

        os.path.isfile()是用来判断文件是否存在的,只能判断文件,不能判断目录,如下所示:

        判断目录:

    import os
    file_path = os.path.abspath(__file__)
    print(os.path.isfile('/home/zhuzhu/第八天'))
    print(os.path.exists("/home/zhuzhu/第八天"))
    输出如下:
    False
    True

        从上面代码可以看出,isfile()是判断文件是否存在,不能够判断目录是否存在,而exists()能够判断目录是否存在。

        判断文件:

    import os
    file_path = os.path.abspath(__file__)
    print(os.path.isfile('file_test'))
    print(os.path.exists("file_test"))
    运行结果如下:
    True
    True

        从上面代码可以看出,isfile()和exists()都能够判断文件是否存在;

        从上面我们得出如下结论,isfile()只能判断文件是否存在,不能够判断目录是否存在;而exists()能够判断文件和目录是否存在。

        其实hashlib就是防止破解的,用户该输入什么就输入什么,只是按照要求的方式,把用户输入的密码加密,以别人看不懂的格式进行存储,防止暴力破解。对客户本身来说是没有影响的,只是表现的方式不一样而已。

        加密:

    import hashlib
    def encryption():
        '''
        对用户输入的内容进行加密
        :return:
        '''
        while True:
            passwrod = input("请输入您的密码>>:")
            m = hashlib.md5()
            m.update(passwrod.encode('utf-8'))
            print("在系统存储的密码如下:%s" %m.hexdigest())
    
    encryption()

        上面代码是对用户输入进行加密处理,加密之后,返回加密后的暗文,其实加密,就是不想别人看到密码原始的样子,如下所示:

    请输入您的密码>>:asdfasfd
    在系统存储的密码如下:7b4dafa43458d3a6a232afdd184ecb53
    请输入您的密码>>:afdsasfd
    在系统存储的密码如下:5ae8c46414716d2b606ff7c7109c6b1b
    请输入您的密码>>:asfda
    在系统存储的密码如下:933a3cde50f232f9f2eb3ef106a7b2d4
    请输入您的密码>>:dfasdf
    在系统存储的密码如下:991d4860883cbdec8effc3f3a3b71bce
    请输入您的密码>>:asdf
    在系统存储的密码如下:912ec803b2ce49e4a541068d495ab570
    请输入您的密码>>:adsf
    a在系统存储的密码如下:05c12a287334386c94131ab8aa00d08a
    请输入您的密码>>:sdf
    在系统存储的密码如下:912ec803b2ce49e4a541068d495ab570
    请输入您的密码>>:asdf
    as在系统存储的密码如下:912ec803b2ce49e4a541068d495ab570
    请输入您的密码>>:df
    在系统存储的密码如下:912ec803b2ce49e4a541068d495ab570
    请输入您的密码>>:asdf
    在系统存储的密码如下:912ec803b2ce49e4a541068d495ab570
    请输入您的密码>>:adsf
    在系统存储的密码如下:05c12a287334386c94131ab8aa00d08a
    请输入您的密码>>:adfs
    在系统存储的密码如下:6a09965fb1ad7f14539e569c264b15ef
    请输入您的密码>>:sadf
    在系统存储的密码如下:fe6d1fed11fa60277fb6a2f73efb8be2
    请输入您的密码>>:12346
    在系统存储的密码如下:a3590023df66ac92ae35e3316026d17d
    请输入您的密码>>:123456a
    在系统存储的密码如下:9cbf8a4dcb8e30682b927f352d6559a0
    请输入您的密码>>:adfa
    d在系统存储的密码如下:4ac174730d4143a119037d9fda81c7a9
    请输入您的密码>>:fas
    在系统存储的密码如下:5a5dc3936c05c32e61aa539e7ffb40c0
    请输入您的密码>>:fdasfd
    a在系统存储的密码如下:a87b8bcbfe5a5030fc01e7688e2bbc94
    请输入您的密码>>:sdf
    在系统存储的密码如下:912ec803b2ce49e4a541068d495ab570
    请输入您的密码>>:asdf
    a在系统存储的密码如下:912ec803b2ce49e4a541068d495ab570
    请输入您的密码>>:sdf
    在系统存储的密码如下:912ec803b2ce49e4a541068d495ab570

        上面,用户输入密码,转换成MD5密码值,这样就是别人看到数据库里面的密码,也不能反解用户的密码,保护用户的隐私。

        os.stat(path)判断文件大小,如下所示:

    import hashlib,os
    file_size = os.stat('file_test')
    print(file_size)
    print(file_size.st_size)
    运行结果如下:
    os.stat_result(st_mode=33204, st_ino=17320086, st_dev=64768, st_nlink=1, st_uid=1000, st_gid=1000, st_size=150, st_atime=1503270341,
    st_mtime=1503270327, st_ctime=1503270327)
    150

        上面文件中,我们使用stat()来判断文件大小,存储属性,取其中的文件大小的属性,得到结果。

        服务器端:

    import socket,os,time,hashlib
    server = socket.socket()
    server.bind(("localhost",9998))
    server.listen()
    while True:
        conn,addr = server.accept()
        print("new conn:",addr)
        while True:
            print("等待新指令")
            data = conn.recv(1024)
            if not data:
                print("客户端已经断开")
                break
            cmd,filename = data.decode().split()    #data是一个byte形式,先转换
            print(filename)
            if os.path.isfile(filename):     #isfile是判断文件是否存在
                f = open(filename,'rb')      #以字节码形式打开
                m = hashlib.md5()
                file_size = os.stat(filename).st_size
                '''hashlib不能直接对文件进行加密'''
                conn.send(str(file_size).encode('utf-8'))
                conn.recv(1024)   #等待客户端接收成功,以便下一次发送   wait for ack
                '''循环发送,读一行发一行'''
                for line in f:
                    # m.update(line)
                    conn.send(line)    #发送文件,循环完成之后发送MD5
                # print("file md5",m.hexdigest())
                f.close()
                
            print('send done')
            
    server.close()

        上面服务器端是接收客户端文件名的指令,然后打开文件,并发送文件的内容,逐行读取并发送给客户端。

        客户端:

    import socket
    client = socket.socket()
    client.connect(("localhost",9998))
    
    while True:
        cmd = input(">>:").strip()
        if len(cmd) == 0:continue
        if cmd.startswith('get'):
            '''代表接收文件'''
            client.send(cmd.encode('utf-8'))
            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')    #文件名不能一样,不然会覆盖之前我文件名
            while received_size < file_total_size:
                data = client.recv(1024)
                received_size += len(data)
                f.write(data)
                # print(file_total_size,received_size)
            else:
                print("file recv done",received_size,file_total_size)
                f.close()
    
    client.close()

        客户端是用来接收数据,并存储到文件中,数据在socket()中的传输,其实就是接收和发送两个步骤,在传输的过程中,只能接收和发送字节,并且两次发送一定要防止粘包,因为发送数据是同步的,因此要客户端完全接收之后,服务器端再进行下一次的发送。

        下面进行MD5验证,加入MD5验证,传输速度会变慢:

  • 相关阅读:
    顺流交易中,母公司销售部分存货,为什么收入也是全额抵消?
    借:递延所得税资产(负债)贷:所得税费用
    可变回报与固定回报
    或有对价
    可以税前扣除什么意思
    应收账款保理为什么是筹资活动
    外币报表折算差额计入其他综合收益
    分配现金股利为什么是筹资
    spring的@EnableAspectJAutoproxy注解
    Spring的@DeclareParents注解
  • 原文地址:https://www.cnblogs.com/gengcx/p/7402350.html
Copyright © 2020-2023  润新知