Python_socket常见的方法、网络编程的安全注意事项、socketsever模块、浏览器中在一段时间记录用户的登录验证机制
1、socket常见的方法
socket_常见方法_服务器端
1 import socket 2 from socket import SOL_SOCKET,SO_REUSEADDR 3 sk = socket.socket() 4 5 sk.setblocking(False)# 设置当前套接字为非阻塞状态 6 sk.settimeout(2)# 秒为单位 设置一下超时时间 7 sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) 8 9 sk.bind(('127.0.0.1',8080)) 10 11 sk.listen(5) 12 13 conn,addr = sk.accept() 14 15 msg = conn.recv(1024) 16 17 print('getpeername:',conn.getpeername(),addr) 18 print('getsockname:',sk.getsockname()) 19 # print('getsockopt:',sk.getsockopt()) 20 print(msg) 21 22 conn.close() 23 sk.close()
socket_常见方法_客户端
1 import socket 2 3 sk = socket.socket(family=socket.AF_UNIX) 4 5 r = sk.connect_ex(('127.0.0.1', 8080)) 6 print('getpeername:', sk.getpeername()) 7 print('getsockname:', sk.getsockname()) 8 9 sk.sendall(b'hello') 10 11 sk.close()
send()与sendall()的区别:
源码:
send()的返回值是发送的字节数量,这个数量可能小于要发送的string的字节数,也就是说可能无法发送string中所有的数据.如果有错则会抛出异常.
send方法相当于有一个自己的拆包机制,如果发送数据量大,可能会进行拆包,此时的拆包和nagle算法没有关系.
sendall()尝试发送string的所有数据,成功则返回None,失败则抛出异常.
sendall() 尝试一次都发出去,如果发不出去,就报错;发出去就返回None.
send()第一次假设发送了8个字节(hello wo),则第二次发送剩下的字节(rld\n).
2、网络编程的安全注意事项
加盐方式:
密文发送到服务器端,再进行二次加密校验;
明文发送到服务器端,然后进行加盐加密校验.
hmac模块
该模块加密是先把数据存储到字典中,然后再进行加密,方法与上述方法类似。
1 import hmac 2 hm = hmac.new(b'abc') 3 hm = hmac.new('萨芬'.encode(encoding='utf-8'),b'bads') 4 print(hm.digest()) 5 print(hm.hexdigest()) 6 注:加密数据时一定要指定数据编码格式
1 import socket 2 import hashlib 3 import os 4 5 sk = socket.socket() 6 7 sk.bind(('127.0.0.1', 8080)) 8 9 sk.listen(5) 10 11 conn, addr = sk.accept() 12 13 salt = b'fuck' 14 r_bytes = os.urandom(32) 15 conn.send(r_bytes) 16 md5_obj = hashlib.md5(salt) 17 md5_obj.update(r_bytes) 18 r = md5_obj.hexdigest() 19 20 client_r = conn.recv(1024).decode('utf-8') 21 22 if r == client_r: 23 print('合法的客户端,可以连接') 24 while True: 25 msg_s = input('>>>').encode('utf-8') 26 conn.send(msg_s) 27 msg_r = conn.recv(1024).decode('utf-8') 28 print(msg_r) 29 else: 30 print('不行') 31 32 conn.close() 33 sk.close()
1 import socket 2 import hashlib 3 4 sk = socket.socket() 5 6 sk.connect(('127.0.0.1', 8080)) 7 8 salt = b'fuck' 9 r_bytes = sk.recv(1024) 10 11 md5_obj = hashlib.md5(salt) 12 md5_obj.update(r_bytes) 13 r = md5_obj.hexdigest() 14 15 sk.send(r.encode('utf-8')) 16 17 while True: 18 msg_r = sk.recv(1024).decode('utf-8') 19 print(msg_r) 20 msg_s = input('>>>').encode('utf-8') 21 sk.send(msg_s) 22 23 sk.close()
加密方式:
登录信息以明文的方式发送至服务器端,在服务器端进行加密后,经过再次加密存储值数据库.
import socket import hmac import os ADDR = ('127.0.0.1', 8080) # 创建套接字,接收客户端的链接 def create_sk(): sk = socket.socket() sk.bind(ADDR) sk.listen(5) conn, addr = sk.accept() return conn, sk # 和客户端通信 def com(): while 1: msg_s = input('>>>').encode('utf-8') conn.send(msg_s) msg_r = conn.recv(1024).decode('utf-8') print(msg_r) # 验证客户端合法性 def check_client(conn): salt = b'fuck' r_bytes = os.urandom(32) conn.send(r_bytes) md5_v = hmac.new(salt, r_bytes) r = md5_v.digest() client_r = conn.recv(1024) if r == client_r: print('合法的客户端,可以连接') com() else: print('不行') return conn, sk = create_sk() check_client(conn) conn.close() sk.close()
1 import socket 2 import hmac 3 4 5 def create_sk(): 6 sk = socket.socket() 7 sk.connect(('127.0.0.1', 8080)) 8 return sk 9 10 11 def md5_login(sk): 12 salt = b'fuck' 13 r_bytes = sk.recv(1024) 14 md5_v = hmac.new(salt, r_bytes) 15 r = md5_v.digest() 16 sk.send(r) 17 18 19 def com(sk): 20 while 1: 21 msg_r = sk.recv(1024).decode('utf-8') 22 print(msg_r) 23 msg_s = input('>>>').encode('utf-8') 24 sk.send(msg_s) 25 26 27 sk = create_sk() 28 md5_login(sk) 29 com(sk) 30 31 sk.close()
3、socketserver模块
socketserver模块(这个模块封装的是并发中的技术).
1 import socketserver 2 3 4 # 并发来实现 5 class MyServer(socketserver.BaseRequestHandler): 6 def handle(self): 7 print(123) 8 self.request.send(b'abc') 9 self.request.recv(1024) 10 11 12 ser = socketserver.ThreadingTCPServer( 13 ('127.0.0.1', 8080), 14 MyServer) 15 16 ser.serve_forever()
客户端写法未变.
1 import socket 2 3 sk = socket.socket() 4 5 sk.connect(('127.0.0.1', 8080)) 6 7 print(sk.recv(b'hello')) 8 9 sk.close()
具体使用:
1 import socketserver 2 import json 3 import hashlib 4 class MyServer(socketserver.BaseRequestHandler): 5 def handle(self): 6 str_dic = self.request.recv(1024).decode('utf-8') 7 dic = json.loads(str_dic) 8 md5_obj = hashlib.md5(dic['username'].encode('utf-8')) 9 md5_obj.update(dic['password'].encode('utf-8')) 10 mw_pwd = md5_obj.hexdigest() 11 with open('userinfo', encoding='utf-8') as f: 12 for line in f: 13 username, passwd = line.strip().split(':') 14 if username.strip() == dic['username'] and passwd.strip() == mw_pwd: 15 print('连接') 16 return 17 print('密码不对') 18 19 server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer) 20 server.server_forever()
1 import socket 2 import json 3 4 sk = socket.socket() 5 6 sk.connect(('127.0.0.1', 8080)) 7 8 username = input('请输入用户名>>>') 9 password = input('请输入密码 >>>') 10 11 dic = {'username': username, 'password': password} 12 str_dic = json.dumps(dic) 13 sk.send(str_dic.encode('utf-8'))
4、浏览器中在一段时间记录用户的登录验证机制
作业:
进度条Python代码的实现:
1 import time 2 def func(): 3 for i in range(1,101,1): 4 num = i // 3 5 print('\r%s%% %s>'%(i,'='*num),end='') 6 time.sleep(0.2) 7 8 9 func()