day8--socket文件傳輸

FTP server數據庫

一、讀取文件名服務器

二、檢測文件是否存在併發

三、打開文件socket

四、檢測文件大小(告訴客戶端發送文件的大小)ui

五、發送文件大小和MD5值給客戶端,MD5加密

六、等待客戶端確認(防止粘包)spa

七、開始邊讀邊發數據3d

八、發送完整的MD5code

九、關閉服務器server

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驗證,傳輸速度會變慢:

相關文章
相關標籤/搜索