• 验证客户端的合法性


    作业讲解

    一对多聊天,不用ip,port来判断和谁聊天

    server端

     1  import socket
     2  friend_lst = {'alex':'32','太白':'33'}
     3  sk =socket.socket(type=socket.SOCK_DGRAM)
     4  sk.bind(('127.0.0.1',9001))
     5  while True:
     6      msg,addr = sk.recvfrom(1500)
     7      msg = msg.decode('utf-8')
     8      name,message  = msg.split('|',1)  # 只切一次
     9      print('33[1;%sm %s:%s33[0m'%(friend_lst.get(name,'30'),name,message))
    10      content = input('>>>')
    11      sk.sendto(content.encode('utf-8'),addr)
    client端
     1  import socket
     2  name = '大壮'
     3  sk = socket.socket(type=socket.SOCK_DGRAM)
     4  5  while True:
     6      content = input('>>>')
     7      if content.upper() == 'Q': break
     8      content = '%s|%s'%(name,content)
     9      sk.sendto(content.encode('utf-8'),('127.0.0.1',9001))
    10      msg = sk.recv(1024).decode('utf-8')
    11      if msg.upper() == 'Q': break
    12      print(msg)

    传送小文件

    server端

     1  import json
     2  import socket
     3  # 接收
     4  sk = socket.socket()
     5  sk.bind(('127.0.0.1',9001))
     6  sk.listen()
     7  8  conn,_ = sk.accept()
     9  msg = conn.recv(1024).decode('utf-8')
    10  msg = json.loads(msg)
    11 12  with open(msg['filename'],'wb') as f:
    13      content = conn.recv(msg['filesize'])
    14      print('-->',len(content))
    15      f.write(content)
    16  conn.close()
    17  sk.close()

    client端

     1  import os
     2  import json
     3  import socket
     4  # 发送
     5  sk = socket.socket()
     6  sk.connect(('127.0.0.1',9001))
     7  8  # 文件名文件大小
     9  abs_path = r'D:python_22day30	mp'
    10  filename = os.path.basename(abs_path)
    11  filesize = os.path.getsize(abs_path)
    12  dic = {'filename':filename,'filesize':filesize}
    13  str_dic = json.dumps(dic)
    14  sk.send(str_dic.encode('utf-8'))
    15 16  with open(abs_path,mode = 'rb') as f:
    17      content = f.read()
    18      sk.send(content)
    19 20  sk.close()

    总结:把文件名和文件大小先做一个字典用json传过去,打开一个同名文件,只接受文件大小的数据

    传送大文件

    server端

     1  import json
     2  import struct
     3  import socket
     4  # 接收
     5  sk = socket.socket()
     6  sk.bind(('127.0.0.1',9001))
     7  sk.listen()
     8  9  conn,_ =sk.accept()
    10  msg_len = conn.recv(4)
    11  dic_len = struct.unpack('i',msg_len)[0]
    12  msg = conn.recv(dic_len).decode('utf-8')
    13  msg = json.loads(msg)
    14 15  with open(msg['filename'],'wb') as f:
    16      while msg['filesize'] > 0:
    17          content = conn.recv(1024)
    18          msg['filesize'] -= len(content)
    19          f.write(content)
    20  conn.close()
    21  sk.close()

    client端

     1  import os
     2  import json
     3  import struct
     4  import socket
     5  # 发送
     6  sk = socket.socket()
     7  sk.connect(('127.0.0.1',9001))
     8  9  # 文件名文件大小
    10  abs_path = r'D:python22期day28 课上视频3.网络基础概念.mp4'
    11  filename = os.path.basename(abs_path)
    12  filesize = os.path.getsize(abs_path)
    13  dic = {'filename':filename,'filesize':filesize}
    14  str_dic = json.dumps(dic)
    15  b_dic = str_dic.encode('utf-8')
    16  mlen = struct.pack('i',len(b_dic))
    17  sk.send(mlen)   # 4个字节 表示字典转成字节之后的长度
    18  sk.send(b_dic)  # 具体的字典数据
    19 20  with open(abs_path,mode = 'rb') as f:
    21      while filesize>0:
    22          content = f.read(1024)
    23          filesize -= len(content)
    24          sk.send(content)
    25  sk.close()

    总结:传送大文件时,不能保证每次接收的都是限定的字节,因为tcp优化会把大文件拆成小文件传送,所以实际接收的文件会比上限要小,应该总文件大小 -= 传过来的内容大小。粘包发生在传送字典时,为了防止粘包所以先传字典长度,因为是一个大文件所以粘包无所谓。

    今日内容

    验证客户端的合法性

    用处

    当需要考虑是否有恶意客户端访问会影响服务器正常运行时。比如恶意客户端会通过扫端口等方法盗取信息或传送非法文件。

    认证机制

    服务端获取一个随机字符串,发送给客户端,之后服务端会把秘钥与发送的内容经过算法得出一个结果,此时客户端也会把秘钥与接收的内容经过同样的算法,将得出的结果发送给服务端,服务端通过比较两者结果是否相同判定客户端是否合法。

    秘钥:用于验证身份的一段约定好的数据

    随机字符串:发送的内容可能会被截获,为了安全一次认证后需换一个随机内容

    算法:hashlib模块

    1  # import os
    2  # ret = os.urandom(16)
    3  # print(ret)
    4 5  # import hashlib
    6  # sha = hashlib.sha1(密钥)
    7  # sha.update(随机字符串)
    8  # 结果 = sha.hexdigest()

    hmac模块

    1  # h = hmac.new(b'alex_sb',os.urandom(32))
    2  # ret = h.digest()
    3  # print(ret)
    实现代码

    server端

     1 import os
     2 import socket
     3 import hashlib
     4 
     5 secret_key = b'alex_sb'
     6 sk = socket.socket()
     7 sk.bind(('127.0.0.1',9001))
     8 sk.listen()
     9 
    10 conn,addr = sk.accept()
    11 # 创建一个随机的字符串
    12 rand = os.urandom(32)
    13 # 发送随机字符串
    14 conn.send(rand)
    15 
    16 # 根据发送的字符串 + secrete key 进行摘要
    17 sha = hashlib.sha1(secret_key)
    18 sha.update(rand)
    19 res = sha.hexdigest()
    20 
    21 # 等待接收客户端的摘要结果
    22 res_client = conn.recv(1024).decode('utf-8')
    23 # 做比对
    24 if res_client == res:
    25     print('是合法的客户端')
    26     # 如果一致,就显示是合法的客户端
    27     # 并可以继续操作
    28     conn.send(b'hello')
    29 else:
    30     conn.close()
    31     # 如果不一致,应立即关闭连接

    client端

     1 import socket
     2 import hashlib
     3 
     4 secret_key = b'alex_sb979'
     5 sk = socket.socket()
     6 sk.connect(('127.0.0.1',9001))
     7 
     8 # 接收客户端发送的随机字符串
     9 rand = sk.recv(32)
    10 # 根据发送的字符串 + secret key 进行摘要
    11 sha = hashlib.sha1(secret_key)
    12 sha.update(rand)
    13 res = sha.hexdigest()
    14 # 摘要结果发送回server端
    15 sk.send(res.encode('utf-8'))
    16 # 继续和server端进行通信
    17 msg = sk.recv(1024)
    18 print(msg)

    并发的tcp协议server端 — socketserver

    socketserver是socket的底层模块

    底层模块

     

    底层模块的效率全看使用者的使用方法

    实现代码

    server端(背)

     1 import time
     2 import socketserver
     3 
     4 class Myserver(socketserver.BaseRequestHandler):
     5     def handle(self):
     6         conn = self.request
     7         while True:
     8             try:
     9                 content = conn.recv(1024).decode('utf-8')
    10                 conn.send(content.upper().encode('utf-8'))
    11                 time.sleep(0.5)
    12             except ConnectionResetError:
    13                 break
    14 server = socketserver.ThreadingTCPServer(('127.0.0.1',9001),Myserver)
    15 server.serve_forever()

    client端(没改动)

    1 import socket
    2 
    3 sk = socket.socket()
    4 sk.connect(('127.0.0.1',9001))
    5 
    6 while True:
    7     sk.send(b'hello')
    8     content = sk.recv(1024).decode('utf-8')
    9     print(content)
  • 相关阅读:
    python 利用pyspark读取HDFS中CSV文件的指定列 列名重命名 并保存回HDFS
    python 利用pandas读取本地中CSV文件的指定列 列名重命名 并保存回本地
    CDH版本Hbase二级索引详细配置方案Solr key value index(二)中文分词
    CDH版本Hbase二级索引详细配置方案Solr key value index
    Seccon2017-pwn500-video_player
    Linux ASLR的实现
    0ctf2017-pages-choices
    33c3-pwn500-recurse
    关于C++中的string的小知识点
    Apache Kylin(三)Kylin上手
  • 原文地址:https://www.cnblogs.com/zhangxiangning/p/10451877.html
Copyright © 2020-2023  润新知