5.soketserver模块实现并发

soketserver模块

soketserver是在socket的基础上进行了一层封装,底层还是调用socket,soketserver可以同时实现多个客户端进行通信,多个人可以同时进行上传下载等.

socketserver客户端

# -*- coding:utf-8 -*-
import socket
client = socket.socket()
client.connect(('127.0.0.1',8001))

while 1:
    msg = input('客户端说>>>')
    client.send(msg.encode('utf-8'))
    from_sesrver_msg = client.recv(1024)
    print(from_sesrver_msg.decode('utf-8'))

socketserver服务端

# -*- coding:utf-8 -*-
#引入模块
import socketserver
#自己写一个类,类名自己随便定义,然后继承
class Myserver(socketserver.BaseRequestHandler):

    def handle(self): #写一个handle方法,必须叫这个名字
        while 1:
            from_client_msg = self.request.recv(1024)
            print(from_client_msg.decode("utf-8"))
            msg = input('服务端说:')
            self.request.send(msg.encode('utf-8'))

if __name__ == '__main__':
    ip_port = ('127.0.0.1',8001)
    server = socketserver.ThreadingTCPServer(ip_port,Myserver) #相当于进行bind,listen
    server.serve_forever() #使服务器一直开着

验证客户端的链接合法性

在客户端链接增加认证功能,利用hmac+盐的方式来实现

客户端

# -*- coding:utf-8 -*-
from socket import *
import hmac
import os

secret_key = b'beijing huan ying ni!'
def conn_auth(conn):
    """
    验证客户端到服务器的链接
    :param conn:
    """
    msg = conn.recv(32)
    h = hmac.new(secret_key,msg)
    digest = h.digest()
    conn.sendall(digest)

def client_handler(ip_port,bufsize=1024):
    tcp_socket_client = socket(AF_INET,SOCK_STREAM)
    tcp_socket_client.connect(ip_port)

    conn_auth(tcp_socket_client)
    while 1:
        data = input('>>:').strip()
        if not data:continue
        if data == 'quit':break

        tcp_socket_client.sendall(data.encode('utf-8'))
        respone = tcp_socket_client.recv(bufsize)
        print(respone.decode('utf-8'))
    tcp_socket_client.close()

if __name__ == '__main__':
    ip_port = ('127.0.0.1',9999)
    bufsize = 1024
    client_handler(ip_port,bufsize)

服务端

# -*- coding:utf-8 -*-
from socket import *
import hmac
import os

secret_key = b'beijing huan ying ni!'
def conn_auth(conn):
    """
    认证客户端链接
    :param conn:
    :return:
    """
    print('开始验证新链接的合法性')
    msg = os.urandom(32) #生成一个32字节的随机字符串
    conn.sendall(msg)
    h = hmac.new(secret_key,msg)
    digest = h.digest()
    respone = conn.recv(len(digest))
    return hmac.compare_digest(respone,digest)

def data_handler(conn,bufsize=1024):
    if not conn_auth(conn):
        print("该链接不合法,关闭")
        conn.close()
        return
    print("链接合法,开始通信")
    while 1:
        data = conn.recv(bufsize)
        if not data:break
        conn.sendall(data.upper())

def server_handler(ip_port,bufsize,backlog=5):
    """
    只处理链接
    :param ip_port:
    :param bufsize:
    :param backlog:
    """

    tcp_socket_server = socket(AF_INET,SOCK_STREAM)
    tcp_socket_server.bind(ip_port)
    tcp_socket_server.listen(backlog)
    while 1:
        conn,addr = tcp_socket_server.accept()
        print( "新链接[%s:%s]" %(addr[0],addr[1]))
        data_handler(conn,bufsize)


if __name__ == '__main__':
    ip_port = ('127.0.0.1',9999)
    bufsize = 1024
    server_handler(ip_port,bufsize)

os.urandom(n)的使用方法

     os.urandom(n)是一种bytes类型的随机生成n个字节字符串的方法,而且每次生成的值不相同.加上md5等加密处理,就能够成内容不同长度相同的字符串

import os
from hashlib import md5

for i in range(10):
    print(md5(os.urandom(32)).hexdigest())

hmac模块

import hmac
message = b'Hello world'
key = b'secret'
h = hmac.new(key,message,digestmod='MD5')
print(h.hexdigest())
#比较两个密文是否相同,可以用hmac.compare_digest(密文,密文),返回True或False 

hmac和普通hash算法非常相似,hmac输出的长度和原始hash算法长度一致,

注意: 传入的key和message都是bytes类型,str类型需要先编码为bytes

import hmac
import random
def hmac_md5(key,s):
    return hmac.new(key.encode('utf-8'),s.encode('utf-8'),'MD5').hexdigest()

class User(object):
    def __init__(self,username,password):
        self.username = username
        self.key = ''.join([chr(random.randint(48,122)) for i in range(20)])
        self.password = hmac_md5(self.key,password)  

  

posted @ 2019-02-24 15:04  等待の喵  阅读(322)  评论(0编辑  收藏