主要内容:
1 . socketserver 模块 :
a : 是出于socket抽象层与应用层之间的一层, 比socket更贴近用户.
b : 主要解决问题 : tcp协议中, 服务器不能同时连接多个客户端的问题
服务器端:
import socketserver
class Mysocket(socketserver.BaseRequestHandler):
def handle(self):
msg_c = self.request.recv(1024).decode('utf-8')
print(msg_c)
self.request.send(msg_c.upper().encode('utf-8'))
socket = socketserver.TCPServer(('127.0.0.1',8090), Mysocket)
socket.serve_forever() #开启一个永久性的服务
客户端:
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8090))
while 1:
msg_s = input('请输入一个英文单词>>>:')
sk.send(msg_s.encode('utf-8'))
print(sk.recv(1024).decode('utf-8'))
sk.close()
注意 :也存在一个问题 : 虽然服务器可以同时接收多个客户端发消息,但是,只能等到第一个客户端发送完了,第二个客户端再发才能接收到消息, 不能同时与多个客户端发消息.
2 . 验证身份
版本一 :
服务器端代码:
import socket
import hashlib
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn, addr = sk.accept()
s = '随意的一个字符串'
sor = 'alex'
conn.send(s.encode('utf-8'))
md5_obj = hashlib.md5(sor.encode('utf-8'))
md5_obj.update(s.encode('utf-8'))
result = md5_obj.hexdigest()
md5_mi = conn.recv(1024).decode('utf-8')
if result == md5_mi:
conn.send('验证成功'.encode('utf-8'))
else:
conn.send('验证失败'.encode('utf-8'))
conn.close()
sk.close()
客户端代码:
import socket
import hashlib
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
sor = 'alex'
s = sk.recv(1024)
md5_obj = hashlib.md5(sor.encode('utf-8'))
md5_obj.update(s)
result = md5_obj.hexdigest()
sk.send(result.encode('utf-8'))
print(sk.recv(1024).decode('utf-8'))
sk.close()
版本二: 版本一的优化
服务器端的代码:
import socket
import hashlib
import hmac
import os
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn, addr = sk.accept()
s = os.urandom(16) #随机出一个num位的随机bytes
sor = 'alex'
conn.send(s)
md5_obj = hmac.new(sor.encode('utf-8'), s)
result = md5_obj.digest()
md5_mi = conn.recv(1024)
if result == md5_mi:
conn.send('验证成功'.encode('utf-8'))
else:
conn.send('验证失败'.encode('utf-8'))
conn.close()
sk.close()
客户端的代码:
import socket
import hashlib
import hmac
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
sor = 'alex'
s = sk.recv(1024)
# 引入hmac,简化代码, 结果直接是bytes
md5_obj = hmac.new(sor.encode('utf-8'), s)
result = md5_obj.digest()
sk.send(result)
print(sk.recv(1024).decode('utf-8'))
sk.close()
3 . 用户的三次登录验证
服务器端代码:
import socketserver
import json
import hashlib
class Mysocket(socketserver.BaseRequestHandler):
def handle(self):
sor = b'thin'
while 1:
str_dic = self.request.recv(1024).decode('utf-8')
if not str_dic: break
dic = json.loads(str_dic)
if not dic['status']:
'''未登录成功'''
with open('userinfo', 'r', encoding='utf-8') as f :
for line in f:
user, pwd = line.strip().split('|')
if user == dic['username']:
md5_obj = hashlib.md5(sor)
md5_obj.update(dic['password'].encode('utf-8'))
result = md5_obj.hexdigest()
if pwd == result:
dic['status'] = True
else:
dic['reason'] = '密码错误'
break
else:
'''用户不存在'''
dic['reason'] = '用户不存在'
str_dic = json.dumps(dic)
self.request.send(str_dic.encode('utf-8'))
else:
# self.request.send('登录成功'.encode())
pass
socket = socketserver.TCPServer(('127.0.0.1', 8888), Mysocket)
socket.serve_forever()
客户端代码:
import socket
import hashlib
import json
sk = socket.socket()
sk.connect(('127.0.0.1', 8888))
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'))
mi_md5 = md5_obj.hexdigest()
dic['username'] = username
dic['password'] = mi_md5
str_dic = json.dumps(dic)
sk.send(str_dic.encode('utf-8'))
# 服务器应该回复我一个这样的字典:
# 是否登录成功,如果没有登录成功是因为什么原因?
res_str = sk.recv(1024).decode('utf-8')
result = json.loads(res_str)
if result['status'] == True:
print('登录成功')
break
else:
print('失败 %s' % result['reason'])
c = c - 1
sk.close()
4 . 进度条
import time
for i in range(51):
time.sleep(0.12)
print('\r' + i*'=' + '>' +str(i * 2) + '%', end='')
输出带颜色的进度条:
import time
for i in range(51):
time.sleep(0.12)
print('\r' +'\033[35m '+ i*'=' + '>' +str(i * 2) + '%'+'\033[0m', end='') # 输出带颜色的进度条.