【第48天】python全棧從入門到放棄

1.什么是socketserver模塊

socketserver模塊是一個(gè)在TCP協(xié)議讓讓一個(gè)服務(wù)端和多個(gè)客戶端通信的一個(gè)模塊

客戶端代碼

代碼塊
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080))

msg_s = input('>>>')
sk.send(msg_s.encode('utf-8'))

print(sk.recv(1024).decode('utf-8'))

sk.close()

服務(wù)端代碼

代碼塊
import socketserver  #用這個(gè)模塊可以多個(gè)客戶端和一個(gè)服務(wù)端通信


class MySocket(socketserver.BaseRequestHandler):
    def handle(self):# 這個(gè)方法的名字是固定的,必須是這個(gè)名字
        # 收發(fā)的邏輯代碼
        # self.request == conn
        msg = self.request.recv(1024).decode('utf-8')
        print(msg)
        self.request.send(msg.upper().encode('utf-8'))



server = socketserver.TCPServer(('127.0.0.1',8080),MySocket)# 固定的
server.serve_forever()# 開啟一個(gè)永久性的服務(wù)

2.實(shí)現(xiàn)客戶端和服務(wù)端大文件的傳輸

客戶端代碼:

代碼塊
import socket
import os
import json
import struct
sk = socket.socket()
sk.connect(("127.0.0.1",8001))

menu = {"1":"upload","2":"download"}
for k,v in menu.items():
    print(k,v)
num = input("請(qǐng)輸入功能選項(xiàng):")
if num == "1":
    dic = {"opt":menu.get(num),"filename":None,"filesize":None}
    file_path = input("請(qǐng)輸入一個(gè)絕對(duì)路徑:")# 文件的絕對(duì)路徑
    # E:\Python S14\day32\實(shí)現(xiàn)大文件的傳輸\11.mp4
    filename = os.path.basename(file_path)# 文件名字
    filesize = os.path.getsize(file_path)# 獲取用戶輸入的路徑中文件的大小
    dic["filename"] = filename
    dic["filesize"] = filesize
    str_dic = json.dumps(dic)   #完成字典的序列化

    len_dic = len(str_dic)# 獲取到字典的長(zhǎng)度攒磨,是一個(gè)int類型的數(shù)據(jù)   假如是46或者146灭返,這不重要
    b_len_dic = struct.pack('i',len_dic)# 把46或者146統(tǒng)一用一個(gè)4bytes的數(shù)據(jù)表示字典的長(zhǎng)度

    sk.send(b_len_dic + str_dic.encode("utf-8"))# 將bytes類型的字典的長(zhǎng)度 + bytes類型的字典的內(nèi)容,一起發(fā)送給服務(wù)器

    with open(file_path,"rb") as f:
        while filesize:
            content = f.read(1024)   #將每次傳輸大小最多控制在1024個(gè)字節(jié)
            sk.send(content)
            filesize -= len(content)

elif num == "2":
    pass

服務(wù)端代碼

代碼塊

import socket
import json
import struct
sk = socket.socket()
sk.bind(("127.0.0.1",8001))
sk.listen()
conn,addr = sk.accept()

b_len_dic = conn.recv(4)
len_dic = struct.unpack('i',b_len_dic)[0]# 獲取到字典的真實(shí)實(shí)際長(zhǎng)度
# unpack得到的是一個(gè)元組涵叮,要取下標(biāo)為0的位置
str_dic = conn.recv(len_dic).decode('utf-8')   #得到字典
# str_dic = {"opt":menu.get(num),"filename":None,"filesize":None}
dic = json.loads(str_dic)    #還原字典

if dic["opt"] == "upload":
    filename = "new"+ dic["filename"]

    with open(filename,"ab") as f:
        while dic['filesize']:
            content = conn.recv(1024)
            f.write(content)
            dic['filesize'] -= len(content)



elif dic["opt"] == "download":
    # 客戶端發(fā)來(lái)一個(gè)字典要執(zhí)行的功能惭蹂,以及客戶端自己的絕對(duì)路徑
    # 服務(wù)器要返回這個(gè)絕對(duì)路徑中所有文件及文件夾
    # 客戶端自己選擇進(jìn)入到哪一層目錄下
    # 服務(wù)器都要返回對(duì)應(yīng)目錄下所有文件及文件夾
    # 客戶隨時(shí)選擇某一個(gè)目錄下的某一個(gè)文件進(jìn)行下載


    # 客戶端發(fā)送來(lái)一個(gè)字典,包含了要進(jìn)行的操作割粮,要下載的文件的絕對(duì)路徑盾碗,
    # 根據(jù)絕對(duì)路徑去讀取文件內(nèi)容
    # 一邊讀,一遍發(fā)
    pass

conn.close()
sk.close()

3.實(shí)現(xiàn)切換目錄的作業(yè)舀瓢,用戶輸入一個(gè)路徑置尔,服務(wù)端返回這個(gè)路徑下所有的文件,如果用戶輸入..氢伟,那么返回上個(gè)目錄層級(jí)榜轿,如果用戶輸入cd,讓用戶輸入要切換的目錄朵锣,服務(wù)器切換到對(duì)應(yīng)的目錄并展示目錄下的文件

客戶端代碼

代碼塊

import socket
import os

sk = socket.socket()
sk.connect(('127.0.0.1',8080))

def func(msg):
    sk.send(msg.encode('utf-8'))  # 發(fā)送
    current_dir = sk.recv(1024).decode('utf-8') #接收
    print(current_dir.split('--'))  # 獲取接收到當(dāng)前目錄的列表類型數(shù)據(jù)


abs_path = input('請(qǐng)輸入您的根目錄:')
func(abs_path)  #執(zhí)行函數(shù)谬盐,發(fā)送和接收

while 1:
    cmd = input('請(qǐng)輸入>>>')
    # cd + 文件夾      ..
    if cmd == '..':
        func(cmd)
    if cmd == 'cd':
        filename = input('請(qǐng)輸入一個(gè)文件夾名:')
        func((cmd+' '+filename))

sk.close()

服務(wù)端代碼

代碼塊
import socket
import os

sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,addr = sk.accept()

def send_data(conn,path):
    '''你給我一個(gè)目錄,我把目錄發(fā)給client'''
    lis_dir = os.listdir(path)   #以列表形式獲取當(dāng)前目錄下的東西
    str_dir = '--'.join(lis_dir)   #將列表拼接成字符串
    conn.send(str_dir.encode('utf-8'))  #發(fā)送給客戶端

current_dir = conn.recv(1024).decode('utf-8')# 獲取用戶輸入的絕對(duì)路徑

# 以下再處理诚些,都要根據(jù)當(dāng)前路徑去處理飞傀,無(wú)論是返回上一層皇型,還是進(jìn)入下一層
send_data(conn,current_dir)# 把用戶輸入的路徑下的所有文件及文件夾返回給客戶端

#D:/泛娛樂(lè)/騎行/第二季

while 1:
    cmd = conn.recv(1024).decode('utf-8')
    if cmd == '..':
        current_dir = current_dir.split('/')[:-1]   #拿到上個(gè)目錄的列表,比如['D:','泛娛樂(lè)','騎行']
        current_dir = '/'.join(current_dir)   #把上個(gè)目錄的里列表轉(zhuǎn)為字符串砸烦,比如D:/泛娛樂(lè)/騎行
        send_data(conn, current_dir)
    else:
        filename = cmd.split(' ')[1]# 獲取用戶輸入的文件名字
        current_dir =current_dir+'/'+filename # 將文件名字添加到當(dāng)前路徑下弃鸦,組成一個(gè)完整的新路徑
        if os.path.isdir(current_dir):# 如果客戶輸入的文件名字是一個(gè)文件夾
            send_data(conn, current_dir)
        else:# 如果不是一個(gè)文件夾
            conn.send('您輸入的不是文件夾'.encode('utf-8'))

conn.close()
sk.close()

4.利用hashlib模塊或者h(yuǎn)mac模塊進(jìn)行md5加密計(jì)算身份驗(yàn)證

代碼塊
import hashlib
import hmac    #相當(dāng)于hashlib,在hashllib基礎(chǔ)上的封裝幢痘,更簡(jiǎn)單
import os

# print(os.urandom(16),len(os.urandom(16)))      #獲取一個(gè)隨即位數(shù)的隨機(jī)數(shù)

sor = b'wusir'
r_str = os.urandom(16)

#用hmac加密
md5_obj = hmac.new(sor,r_str)
r = md5_obj.digest()
print(r)

#用hsahlib加密
md5_obj = hashlib.md5(sor)
md5_obj.update(r_str)
r1 = md5_obj.hexdigest()

5.利用hmac完成登陸驗(yàn)證的例子

客戶端代碼

代碼塊
import socket
import hmac
sk = socket.socket()
sk.connect(('127.0.0.1',8080))

sor = b'alex'

r_str = sk.recv(1024)   # 獲得服務(wù)端16位長(zhǎng)度的bytes

md5_obj = hmac.new(sor,r_str)
result = md5_obj.digest()

sk.send(result)  #將md5加密后發(fā)給服務(wù)端

msg = sk.recv(1024)
print(msg)

服務(wù)端代碼

代碼塊

import socket
import hashlib
import os
import hmac
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,addr = sk.accept()


sor = b'alex'
r_str = os.urandom(16)# 隨機(jī)出一個(gè)16位長(zhǎng)度的bytes
conn.send(r_str)

md5_obj = hmac.new(sor,r_str)
result = md5_obj.digest()


msg = conn.recv(1024)    #接收客戶端md5加密后的密文
if msg == result:
    conn.send(b'success')
else:
    conn.send(b'failed')


conn.close()
sk.close()

6.三次登陸

客戶端代碼

代碼塊
import socket
import hashlib
import json
sk = socket.socket()
sk.connect(('127.0.0.1',8080))

dic = {'status':False,'username':None,'password':None}
c = 3  #允許用戶登陸3次

while c:
    username = input('請(qǐng)輸入用戶名')
    password = input('請(qǐng)輸入密碼')

    md5_obj = hashlib.md5(password.encode('utf-8'))
    md5_obj.update(username.encode('utf-8'))
    pawd_m = md5_obj.hexdigest()    #得到一個(gè)加密算法

    dic['username'] = username
    dic['password'] = pawd_m
    str_dic = json.dumps(dic)
    sk.send(str_dic.encode('utf-8'))   #發(fā)送序列化后的字典

    # 服務(wù)器應(yīng)該回復(fù)我一個(gè)這樣的字典:
    # 是否登錄成功唬格,如果沒(méi)有登錄成功是因?yàn)槭裁丛颍?    res_dic = sk.recv(1024).decode('utf-8')# str_dic
    result = json.loads(res_dic)# dic = {status:False/True ,  username ,   password,   reason}
    if result['status']:
        print('登錄成功')
        break
    else:
        print('失敗,%s'%result['reason'])
        c -= 1

sk.close()

服務(wù)端代碼

代碼塊
import socketserver
import json
import hashlib


class MySocket(socketserver.BaseRequestHandler):
    def handle(self):
        sor = b'wusir'#
        while 1:
            str_dic = self.request.recv(1024).decode('utf-8')
            # 接收到 一個(gè)字典颜说,類似于{'status':False,'username':None,'password':None}
            if not str_dic:break # 當(dāng)客戶端登錄失敗退出程序的情況下购岗,這里會(huì)接收到一個(gè)空消息。
            dic = json.loads(str_dic)   #還原為原來(lái)字典
            if not dic['status']:
                '''狀態(tài)是未登陸'''
                with open('info','r',encoding='utf-8') as f:
                    # 文件內(nèi)容的存儲(chǔ)方式  用戶名|密碼
                    for info in f:
                        username,pawd_txt = info.strip().split('|')
                        if username == dic['username']:
                            '''用戶存在门粪,就對(duì)客戶端發(fā)來(lái)的用戶的加密 密碼再次加密喊积,與文件中對(duì)比'''
                            md5_obj = hashlib.md5(sor)
                            md5_obj.update(dic['password'].encode('utf-8'))
                            pawd = md5_obj.hexdigest()
                            if pawd_txt == pawd:
                                '''密碼正確的情況下'''
                                dic['status'] = True
                            else:
                                dic['reason'] = '密碼錯(cuò)誤'
                            break
                    else:
                        '''用戶不存在'''
                        dic['reason'] = '用戶不存在'
                #  dic = {status:False ,  username ,   password,   reason}
                #  dic = {status:True ,  username ,   password}
                str_dic = json.dumps(dic)
                self.request.send(str_dic.encode('utf-8'))
            else:
                '''已經(jīng)是登錄成功了'''

server = socketserver.TCPServer(('127.0.0.1',8080),MySocket)
server.serve_forever()   #永久開啟服務(wù),不關(guān)閉

文件的內(nèi)容玄妈,文件名:info

alex|d32aa373dec2e4ba7861190083d1da83
xiaoxue|0cb576a05f23a9557278f41329c8dee1

7.對(duì)用戶名和密碼加密后乾吻,發(fā)送到服務(wù)端,服務(wù)端再對(duì)密碼進(jìn)行加密拟蜻,然后與數(shù)據(jù)庫(kù)比對(duì)

代碼塊
import hashlib

sor=b'wusir'  #鹽

pwd='123456'
user='alex'
#客戶端對(duì)密碼進(jìn)行第一次加密
md5_obj=hashlib.md5(pwd.encode('utf-8'))
md5_obj.update(user.encode('utf-8'))
res=md5_obj.hexdigest()


#服務(wù)端接收客戶端傳過(guò)來(lái)的密碼溶弟,再利用鹽,進(jìn)行二次加密瞭郑,然后與數(shù)據(jù)庫(kù)比對(duì)辜御。
md5_obj1=hashlib.md5(sor)
md5_obj1.update(res.encode('utf-8'))
res1=md5_obj1.hexdigest()
print(res1)  #d32aa373dec2e4ba7861190083d1da83

8. prite()相當(dāng)調(diào)用sys.stdout.write()

代碼塊
import sys
name='hello'
sys.stdout.write(name)    #print()就相當(dāng)于調(diào)用底層sys.stdout.write(name)

9. 如何通過(guò)cmd導(dǎo)入python第三方包

pip install 包的名字
例如:pip install Django

別跑,點(diǎn)個(gè)贊再走
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末屈张,一起剝皮案震驚了整個(gè)濱河市擒权,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌阁谆,老刑警劉巖碳抄,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異场绿,居然都是意外死亡剖效,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門焰盗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)璧尸,“玉大人,你說(shuō)我怎么就攤上這事熬拒∫猓” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵澎粟,是天一觀的道長(zhǎng)蛀序。 經(jīng)常有香客問(wèn)我欢瞪,道長(zhǎng),這世上最難降的妖魔是什么徐裸? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任遣鼓,我火速辦了婚禮,結(jié)果婚禮上重贺,老公的妹妹穿的比我還像新娘骑祟。我一直安慰自己,他們只是感情好檬姥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布曾我。 她就那樣靜靜地躺著粉怕,像睡著了一般健民。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贫贝,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天秉犹,我揣著相機(jī)與錄音,去河邊找鬼稚晚。 笑死崇堵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的客燕。 我是一名探鬼主播鸳劳,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起恨课,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤立镶,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后废睦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年既忆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗦玖。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡患雇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宇挫,到底是詐尸還是另有隱情庆亡,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布捞稿,位于F島的核電站又谋,受9級(jí)特大地震影響拼缝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜彰亥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一咧七、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧任斋,春花似錦继阻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至澈蟆,卻和暖如春墨辛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背趴俘。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工睹簇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人寥闪。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓太惠,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親疲憋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凿渊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354