33 socketserver模块、进度条、hmac模块、验证身份(subprocess模块、struct模块复习、)

复习一下:
socket模块 :套接字,网络传输数据,处于应用层和传输层之间的一个抽象层
  

 

 

 

socket模块更多用法:(了解)
  
服务端套接字函数
s.bind()    绑定(主机,端口号)到套接字
s.listen()  开始TCP监听
s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来

客户端套接字函数
s.connect()     主动初始化TCP服务器连接
s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数
s.recv()            接收TCP数据
s.send()            发送TCP数据
s.sendall()         发送TCP数据
s.recvfrom()        接收UDP数据
s.sendto()          发送UDP数据
s.getpeername()     连接到当前套接字的远端的地址
s.getsockname()     当前套接字的地址
s.getsockopt()      返回指定套接字的参数
s.setsockopt()      设置指定套接字的参数
s.close()           关闭套接字

面向锁的套接字方法
s.setblocking()     设置套接字的阻塞与非阻塞模式
s.settimeout()      设置阻塞套接字操作的超时时间
s.gettimeout()      得到阻塞套接字操作的超时时间

面向文件的套接字的函数
s.fileno()          套接字的文件描述符
s.makefile()        创建一个与该套接字相关的文件
更多方法

subprocess模块 :Popen方法:执行操作系统命令的
import subprocess

r = subprocess.Popen('dir', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

# cmd : 代表系统命令
# shell = True   代表这条命令是 系统命令,告诉操作系统,将cmd当成系统命令去执行
# stdout   是执行完系统命令之后,用于保存结果的一个管道
# stderr   是执行完系统命令之后,用于保存错误结果的一个管道

print("stdout:", r.stdout.read().decode('gbk'))
print("stderr:", r.stderr.read().decode('gbk'))
subprocess 模块

struct模块:pack和unpack方法
  把一个数字打包成一个四字节的bytes,
  解包
# struct.pack(type,num)
# type:是num的类型   'i'\'f'\'l'\'d'
# num :是一个数字
# r = struct.pack(type,num)
# struct.unpack(type,r)

import struct

r = struct.pack('i',52)
print(r, len(r))
z = struct.unpack('i',r)
print(z)
struct

 

 

简单的进度条

   \r 默认将指针返回到最开始后输出(在原位置再次输出)。借助\r,可以让进度条在一行上不断更新

import time
# 1024*15 / 1500000
for i in range(51):
    time.sleep(0.13)
    print( i*'=' + '>' + str(i*2) + '%',end='')
进度条

 

socketserver模块

    socketserver这个模块主要是为了解决:
     TCP协议中,服务器不能同时连接多个客户端的问题
        是处于socket抽象层和应用层之间的一层,比socket更贴近用户
import socketserver


class MySocket(socketserver.BaseRequestHandler):
    def handle(self):# 这个方法的名字是固定的,必须是这个名字
        # 收发的逻辑代码
        # 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()# 开启一个永久性的服务
server
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()
client

 

hamc模块

md5_obj = hmac.new(sor, r_str)
result = md5_obj.digest()  # 拿到一个bytes的结果
hamc方法
加密算法一般使用的是hashlib,
在这里简便成,使用hmac这个新模块中的new方法,去进行加密
md5_obj = hmac.new(盐,随机字符串)
r = md5_obj.digest()
拿到一个bytes的结果,也就是密文,也不必编码了

回顾一下:
sor = b'zhuangdd'
r_str = '这是一个随机的字符串'

md5_obj = hashlib.md5(sor)
md5_obj.update(r_str.encode('utf-8'))
result = md5_obj.hexdigest()
hashlib加密

 

身份验证

import socket
import hmac
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
sor = b'alex'
r_str = sk.recv(1024)

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

sk.send(result)

msg = sk.recv(1024)
print(msg)
client
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)# 随机出一个16位长度的bytes
conn.send(r_str)

md5_obj = hmac.new(sor, r_str)
result = md5_obj.digest()  # 拿到一个bytes的结果

msg = conn.recv(1024)
if msg == result:
    conn.send(b'success')
else:
    conn.send(b'failed')


conn.close()
sk.close()
server

 

 

最后 实现三次登录的功能

import socketserver
import json
import hashlib

def zhuce():
    pass

class MySocket(socketserver.BaseRequestHandler):
    def handle(self):
        sor = b'wusir'#
        while 1:
            str_dic = self.request.recv(1024).decode('utf-8')
            # 接收到 一个字典,类似于{'status':False,'username':None,'password':None}
            if not str_dic:break # 当客户端登录失败退出程序的情况下,这里会接收到一个空消息。
            dic = json.loads(str_dic)
            if not dic['status']:
                '''没有登录成功的情况下'''
                with open('info', 'r', encoding='utf-8') as f:
                    # 文件内容的存储方式  用户名|密码
                    for info in f:
                        username,pawd_txt = info.strip().split('|')
                        if username == dic['username']:
                            '''用户存在,就对客户端发来的用户的密码再次加密,与文件中对比'''
                            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'] = '密码错误'
                            break
                    else:
                        '''用户不存在'''
                        dic['reason'] = '用户不存在'
                        zhuce()
                #  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:
                '''已经是登录成功了'''

server = socketserver.TCPServer(('127.0.0.1',8080),MySocket)
server.serve_forever()
server
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
while c:
    username = input('请输入用户名')
    password = input('请输入密码')

    md5_obj = hashlib.md5(password.encode('utf-8'))
    md5_obj.update(username.encode('utf-8'))
    pawd_m = md5_obj.hexdigest()

    dic['username'] = username
    dic['password'] = pawd_m
    str_dic = json.dumps(dic)
    sk.send(str_dic.encode('utf-8'))

    # 服务器应该回复我一个这样的字典:
    # 是否登录成功,如果没有登录成功是因为什么原因?
    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()
client

 

posted @ 2020-04-20 09:52  蜗牛般庄  阅读(143)  评论(0编辑  收藏  举报
Title
页脚 HTML 代码