1、websocket

	1.websocket 与轮询
轮询:
不断向服务器发起询问,服务器还不断的回复
浪费带宽,浪费前后端资源
保证数据的实时性 长轮询:
1.客户端向服务器发起消息,服务端轮询,放在另外一个地方,客户端去另外一个地方去拿
2.服务端轮询,放在另外一个地方,直接推给客户端 释放客户端资源,服务压力不可避免,节省带宽资源
数据不能实时性 websocket:是一个新的协议 Socket-io
1.前后端hold住
2.建立长链接 彻底解决实时性
解决占用带宽的问题
解决资源 2.webscoket使用
from flask import Flask, request
from geventwebsocket.websocket import WebSocket
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler app = Flask(__name__) @app.route("/ws") # WS://127.0.0.1:9527/ws
def ws():
# request.environ["wsgi.websocket"] = <链接>
user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
while 1:
msg = user_socket.receive()
print(msg)
user_socket.send(msg) if __name__ == '__main__':
http_serv = WSGIServer(("0.0.0.0", 9527), app, handler_class=WebSocketHandler)
http_serv.serve_forever()
# app.run("0.0.0.0", 9527, debug=True) 即时通讯(IM):
群聊:
from flask import Flask, request,render_template
from geventwebsocket.websocket import WebSocket
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
import json app = Flask(__name__) user_socket_dict = {} # {jinwangba:<geventwebsocket.websocket.WebSocket object at 0x000000000B35CE18>} @app.route("/")
def index():
return render_template("index.html") @app.route("/ws/<nickname>") # WS://127.0.0.1:9527/ws
def ws(nickname):
user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
if user_socket:
user_socket_dict[nickname]=user_socket
print(len(user_socket_dict))
else:
return render_template("index.html",message="请使用Websocket链接")
while 1:
msg = user_socket.receive()
for user_nick_name,socket in user_socket_dict.items(): # type:WebSocket
if user_socket != socket:
try:
socket.send(json.dumps({"sender":nickname,"msg":msg}))
except:
continue if __name__ == '__main__':
http_serv = WSGIServer(("0.0.0.0",9527),app,handler_class=WebSocketHandler)
http_serv.serve_forever()
# app.run("0.0.0.0", 9527, debug=True) 单聊:
from flask import Flask, request,render_template
from geventwebsocket.websocket import WebSocket
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
import json app = Flask(__name__) user_socket_dict = {} # {jinwangba:<geventwebsocket.websocket.WebSocket object at 0x000000000B35CE18>} @app.route("/")
def index():
return render_template("index.html") @app.route("/ws/<nickname>") # WS://127.0.0.1:9527/ws
def ws(nickname):
user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
if user_socket:
user_socket_dict[nickname]=user_socket
print(len(user_socket_dict),user_socket_dict)
else:
return render_template("index.html",message="请使用Websocket链接")
while 1:
msg = user_socket.receive()
msg_dict = json.loads(msg)
#{"to_user":jinwangba,msg:"DSB"}
to_user = msg_dict.get("to_user")
print("to_user:",to_user)
to_user_socket = user_socket_dict.get(to_user)
send_str = json.dumps({"sender":nickname,"msg":msg_dict.get("msg")})
to_user_socket.send(send_str) if __name__ == '__main__':
http_serv = WSGIServer(("0.0.0.0",9527),app,handler_class=WebSocketHandler)
http_serv.serve_forever()
# app.run("0.0.0.0", 9527, debug=True)

  

2、websocket原理
  

import socket, base64, hashlib

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', 9527))
sock.listen(5)
# 获取客户端socket对象
conn, address = sock.accept()
# 获取客户端的【握手】信息
data = conn.recv(1024)
print(data) def get_headers(data):
header_dict = {}
header_str = data.decode("utf8")
for i in header_str.split("\r\n"):
if str(i).startswith("Sec-WebSocket-Key"):
header_dict["Sec-WebSocket-Key"] = i.split(":")[1].strip() return header_dict ws_key = get_headers(data).get("Sec-WebSocket-Key") # # magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11
magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
socket_str = ws_key + magic_string
socket_str_sha1 = hashlib.sha1(socket_str.encode("utf8")).digest()
socket_str_base64 = base64.b64encode(socket_str_sha1) response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \
"Upgrade:websocket\r\n" \
"Connection: Upgrade\r\n" \
"Sec-WebSocket-Accept: %s\r\n" \
"WebSocket-Location: ws://127.0.0.1:9527\r\n\r\n" %(socket_str_base64.decode("utf8")) conn.send(response_tpl.encode("utf8"))
while 1:
msg = conn.recv(8096)
print(msg) """
b'GET / HTTP/1.1\r\n
Host: 127.0.0.1:9527\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:62.0) Gecko/20100101 Firefox/62.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\r\n
Accept-Encoding: gzip, deflate\r\n
Sec-WebSocket-Version: 13\r\n
Origin: http://localhost:63342\r\n
Sec-WebSocket-Extensions: permessage-deflate\r\n
Sec-WebSocket-Key: x/BjPHeWzOqqLxVuZq/bfw==\r\n
Cookie: session=fe2f4896-0309-4801-b8cd-9a719b26fb8d\r\n
Connection: keep-alive, Upgrade\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
Upgrade: websocket\r\n\r\n'
""" # # magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11
# magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
#
#
# def get_headers(data):
# header_dict = {}
# header_str = data.decode("utf8")
# for i in header_str.split("\r\n"):
# if str(i).startswith("Sec-WebSocket-Key"):
# header_dict["Sec-WebSocket-Key"] = i.split(":")[1].strip()
#
# return header_dict
#
#
# def get_header(data):
# """
# 将请求头格式化成字典
# :param data:
# :return:
# """
# header_dict = {}
# data = str(data, encoding='utf-8')
#
# header, body = data.split('\r\n\r\n', 1)
# header_list = header.split('\r\n')
# for i in range(0, len(header_list)):
# if i == 0:
# if len(header_list[i].split(' ')) == 3:
# header_dict['method'], header_dict['url'], header_dict['protocol'] = header_list[i].split(' ')
# else:
# k, v = header_list[i].split(':', 1)
# header_dict[k] = v.strip()
# return header_dict
#
#
# headers = get_headers(data) # 提取请求头信息
# # 对请求头中的sec-websocket-key进行加密
# response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \
# "Upgrade:websocket\r\n" \
# "Connection: Upgrade\r\n" \
# "Sec-WebSocket-Accept: %s\r\n" \
# "WebSocket-Location: ws://127.0.0.1:9527\r\n\r\n" # value = headers['Sec-WebSocket-Key'] + magic_string
# print(value)
# ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest())
# response_str = response_tpl % (ac.decode('utf-8'))
# # 响应【握手】信息
# conn.send(response_str.encode("utf8"))
#
# while True:
# msg = conn.recv(8096)
# print(msg)

websocket加解密

3、websocket加解密
  

上节回顾:
websocket;握手
浏览器 - 链接 - 服务器
浏览器 - 发送 - 字符串(求情头) - Sec-Websocket-Key - 服务器 服务器 - 获取Sec-Websocket-Key的值+magic_string - sha1 - base64 - 拼接一个响应头 - Sec-WebSocket-Accept值就是
服务器 - 拼接好的响应头 - 浏览器
浏览器 - Sec-WebSocket-Accept 解密得到 Sec-Websocket-Key - 握手成功与否 今日内容:
websocket 加解密
解密:
b_str = b'\x81\xfe\x01G\xa0`~dE\xe5\xf6\x81\x18\xfd\x9b\xec;\x84\xc6\xfeF\xfc\xd4\x81-\xea\x96\xe4,\x84\xc6\xc9I\xe1\xed\x81\x14\xc9\x98\xca"\x8f\xc2\xe8D\xdb\xf4\x81\x04\xc9\x9a\xdc+\x84\xc6\xedE\xe8\xf8\x8b\x1c\xec\x99\xff*\x85\xc9\xfaG\xf6\xcc\x81\x1c\xea\x91\xd8,\x86\xd3\xc0H\xcf\xe4\x81-\xd1\x98\xe4\x05\x85\xd3\xfcD\xda\xdf\x80\x19\xeb\x99\xc3+\x84\xc7\xfbC\xe0\xfc\x83$\xd6\x9a\xda-\x85\xf3\xcfD\xd9\xf5\x8c\'\xc3\x9a\xdc-\x86\xf9\xecD\xda\xf0\x81&\xe5\x91\xd8,\x85\xc1\xc4E\xdf\xe9\x80\x19\xeb\x9b\xc7\x0b\x85\xc1\xfcH\xda\xd5\x80\x1a\xee\x9b\xc06\x88\xfe\xe1O\xdc\xf2\x83;\xf6\x96\xdb\x1d\x85\xfb\xecE\xd8\xe3\x80\x19\xeb\x98\xca*\x89\xff\xe3O\xdc\xf2\x82\x0c\xd2\x98\xee\x05\x84\xc7\xefD\xda\xf0\x8d9\xfb\x9a\xdc+\x84\xc7\xfbC\xe0\xfc\x8c\x0f\xfa\x9b\xca<\x85\xc2\xe4E\xdc\xde\x81<\xc3\x9b\xf4\x0c\x8f\xc2\xe8D\xdb\xdb\x81%\xe9\x9b\xe1(\x85\xc6\xf9I\xe1\xe9\x81\x1e\xd7\x91\xd8,\x86\xff\xc6E\xdc\xe6\x81\x1f\xf7\x9b\xc7\x0b\x84\xc7\xefF\xd0\xea\x8b\x1c\xec\x9a\xdc-\x85\xd0\xf8E\xc6\xfa\x8c\'\xca\x96\xeb\x12\x88\xe8\xe0O\xdc\xf2\x81\x1c\xf5\x9b\xf2\x1b\x85\xda\xd5D\xd9\xf7\x8b\x1c\xec\x9a\xdf\x05\x85\xdf\xfaE\xdf\xde\x8c\x10\xef\x9a\xdd+\x88\xc9\xcbD\xd9\xe1'
c_str = b'\x81\xfe\x02d\xbe@<\x07'
# 123 \x81
#[\x81,\x83,\xc8,\xbd,\xa6,\x9c,\xf9,\x8f,\x95]
#
#
#
#--------
#
# 0111111 127
# 0111110 126 data_lenth = b_str[1] & 127
# print(data_lenth) # data_lenth == 127 之后的多少位为数据长度3-10字节代表数据长度 11-14为mask_key
if data_lenth == 127:
extend_payload_len = b_str[2:10]
mask = b_str[10:14]
data = b_str[14:] # data_lenth == 126 之后的多少位为数据长度3-4字节代表数据长度 65535 5-8为mask_key
if data_lenth == 126:
extend_payload_len = b_str[2:4]
mask = b_str[4:8]
data = b_str[8:] # data_lenth <= 125 当前的 data_lenth 就是数据的长度 125 3-6为mask_key
if data_lenth <= 125:
extend_payload_len = b_str[1]
mask = b_str[2:6]
data = b_str[6:] str_byte = bytearray() for i in range(len(data)):
byte = data[i] ^ mask[i % 4] #
str_byte.append(byte) print(str_byte.decode("utf8"))# 加密:
import struct
msg_bytes = "先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也".encode("utf8")
token = b"\x81"
length = len(msg_bytes) if length < 126:
token += struct.pack("B", length)
elif length == 126:
token += struct.pack("!BH", 126, length)
else:
token += struct.pack("!BQ", 127, length) msg = token + msg_bytes print(msg)

websocket握手和加解密

4、人工智能简易机器人
  

1.百度ai
2.基于百度ai实现了语音合成
3.基于百度ai实现了语音识别

from aip import AipSpeech
import os
from uuid import uuid4
from wav2pcm import wav_to_pcm APP_ID = ''
API_KEY = 'zdU6ldOh7CeQvFFzw9GWhwZr'
SECRET_KEY = 'h5eVzR2G4EPFf78uzceC1zHL6Qj88RCY' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # client.setConnectionTimeoutInMillis(5000) # 建立连接的超时时间(单位:毫秒)
# client.setSocketTimeoutInMillis(10000) # 通过打开的连接传输数据的超时时间(单位:毫秒)
# 语音合成
def new_synthesis(text):
result = client.synthesis(text, 'zh', 1, {
'vol': 5, # 音量,取值0-15,默认为5中音量
'spd': 5, # 语速,取值0-9,默认为5中语速
'pit': 5, # 音调,取值0-9,默认为5中语调
'per': 4 # 发音人选择, 0为女声,1为男声,3为情感合成-度逍遥,4为情感合成-度丫丫,默认为普通女
})
audio_file_path = str(uuid4()) + ".mp3"
# 识别正确返回语音二进制 错误则返回dict 参照下面错误码
if not isinstance(result, dict):
with open(audio_file_path, 'wb') as f:
f.write(result)
return audio_file_path # 读取文件
def get_file_content(pcm_file_path):
with open(pcm_file_path, 'rb') as fp:
return fp.read() # 语音识别
def new_asr(filePath):
# 将录音机文件wma转换成pcm
pcm_file_path = wav_to_pcm(filePath) # 识别本地文件
res = client.asr(get_file_content(pcm_file_path), 'pcm', 16000, {
'dev_pid': 1536,
})
try:
text = res.get('result')[0]
except Exception as e:
text = "对不起,没有听清你说的啥,请再说一遍。"
os.remove(pcm_file_path)
return text if __name__ == '__main__':
new_asr('audio.wma')

语音合成和语音识别

FFmpeg 转换PCM音频格式

# wav2pcm.py 文件内容
import os def wav_to_pcm(wav_file):
# 假设 wav_file = "音频文件.wav"
# wav_file.split(".") 得到["音频文件","wav"] 拿出第一个结果"音频文件" 与 ".pcm" 拼接 等到结果 "音频文件.pcm"
pcm_file = "%s.pcm" % (wav_file.split(".")[0]) # 就是此前我们在cmd窗口中输入命令,这里面就是在让Python帮我们在cmd中执行命令
os.system("ffmpeg -y -i %s -acodec pcm_s16le -f s16le -ac 1 -ar 16000 %s" % (wav_file, pcm_file))
os.remove(wav_file)
return pcm_file

wav2pcm.py

4.基于百度ai NLP技术中的Simnet 实现 短文本相似度

# 基于百度ai的Simnet的 实现短文本相似度
from aip import AipNlp APP_ID = ''
API_KEY = 'zdU6ldOh7CeQvFFzw9GWhwZr'
SECRET_KEY = 'h5eVzR2G4EPFf78uzceC1zHL6Qj88RCY' client = AipNlp(APP_ID, API_KEY, SECRET_KEY) def new_simnet(text1, text2):
ret = client.simnet(text1, text2)
return ret.get('score')

基于百度ai的Simnet的 实现短文本相似度

5.简单问答 + Tuling机器人
  

import requests

def tuling_answer(text):
to_tuling_url = "http://openapi.tuling123.com/openapi/api/v2" # 接口地址
json_data = {
"reqType": 0,
"perception": {
"inputText": {
"text": text
},
},
"userInfo": {
"apiKey": "93e5736f3b9e496bbb63a0f29afa4d4d",
"userId": "test123"
}
}
res = requests.post(to_tuling_url, json=json_data).json()
answer = res.get("results")[0]['values']['text']
return answer if __name__ == '__main__': tuling_answer('北京天气')

tuling_answer

6.web录音知道里面是干什么的,Audio标签 src音频地址 autoplay当src加载完成时自动播放 controls 显示或关闭播放器

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title> </head>
<body>
<audio src="" autoplay controls id="player"></audio> <button onclick="start_reco()">录制消息</button>
<br>
<button onclick="stop_reco()">发送语音消息</button> </body>
<script src="/static/Recorder.js"></script>
<script type="application/javascript">
var serv = "http://127.0.0.1:9527";
var ws_serv = "ws://127.0.0.1:9528/ws"; var get_music = serv + "/get_audio/";
var ws = new WebSocket(ws_serv);
ws.onmessage = function (data) {
console.log(data.data,111111111)
document.getElementById("player").src = get_music + data.data
};
var reco = null;
var audio_context = new AudioContext();
navigator.getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia); navigator.getUserMedia({audio: true}, create_stream, function (err) {
console.log(err)
}); function create_stream(user_media) {
var stream_input = audio_context.createMediaStreamSource(user_media);
reco = new Recorder(stream_input);
} function start_reco() {
reco.record();
} function stop_reco() {
reco.stop();
get_audio();
reco.clear();
} function get_audio() {
reco.exportWAV(function (wav_file) {
ws.send(wav_file);
})
} </script>
</html>

html

7.基于websocket传输语音
8.return send_file(file_name)
  

from flask import Flask, send_file, render_template
from queue import Queue
import os
q = Queue() # type:Queue app = Flask(__name__) # type:Flask @app.route("/index")
def index():
return render_template("index1.html") temp_file_name = [] @app.route('/get_audio/<filename>')
def get_audio(filename):
# 利用队列存储临时生成的文件名,下一次请求来的时候删除文件
if not q.empty():
temp = q.get()
print(temp)
os.remove(temp)
q.put(filename)
return send_file(filename) if __name__ == '__main__':
app.run(host='0.0.0.0', port=9527)

flask_app.py

from flask import Flask, request
from geventwebsocket.websocket import WebSocket
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
from uuid import uuid4 from baidu_asr_and_synthesis import new_asr, new_synthesis
from simple_questions_answers import question_answer app = Flask(__name__) # type:Flask @app.route('/ws')
def ws():
user_websocket = request.environ.get('wsgi.websocket') # type:WebSocket
if user_websocket:
while 1:
res = user_websocket.receive()
# 保存接收音频文件
rev_file_name = ("%s" + ".wav") % str(uuid4())
with open(rev_file_name, 'wb') as f:
f.write(res)
print(rev_file_name)
# 将接收的音频文件转换为文本
audio_to_text = new_asr(rev_file_name)
print('audio_to_text',audio_to_text)
# 根据问题文本回答问题
answer_text = question_answer(audio_to_text)
print('answer_text',answer_text)
# 将问题答案转成音频文件
answer_audio_file_path = new_synthesis(answer_text)
print('answer_audio_file_path',answer_audio_file_path)
# 将音频文件路径发给前端
user_websocket.send(answer_audio_file_path) if __name__ == '__main__':
http_serv = WSGIServer(('0.0.0.0', 9528), app, handler_class=WebSocketHandler)
http_serv.serve_forever()

flask_ws.py

python全栈开发day115、116-websocket、websocket原理、websocket加解密、简单问答机器人实现的更多相关文章

  1. Python全栈开发【面向对象进阶】

    Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...

  2. Python全栈开发【面向对象】

    Python全栈开发[面向对象] 本节内容: 三大编程范式 面向对象设计与面向对象编程 类和对象 静态属性.类方法.静态方法 类组合 继承 多态 封装 三大编程范式 三大编程范式: 1.面向过程编程 ...

  3. Python全栈开发【模块】

    Python全栈开发[模块] 本节内容: 模块介绍 time random os sys json & picle shelve XML hashlib ConfigParser loggin ...

  4. Python全栈开发【基础四】

    Python全栈开发[基础四] 本节内容: 匿名函数(lambda) 函数式编程(map,filter,reduce) 文件处理 迭代器 三元表达式 列表解析与生成器表达式 生成器 匿名函数 lamb ...

  5. Python全栈开发【基础三】

    Python全栈开发[基础三]  本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...

  6. Python全栈开发【基础二】

    Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 其他(编码,range,f ...

  7. Python全栈开发【基础一】

    Python全栈开发[第一篇] 本节内容: Python 的种类 Python 的环境 Python 入门(解释器.编码.变量.input输入.if流程控制与缩进.while循环) if流程控制与wh ...

  8. python 全栈开发之路 day1

    python 全栈开发之路 day1   本节内容 计算机发展介绍 计算机硬件组成 计算机基本原理 计算机 计算机(computer)俗称电脑,是一种用于高速计算的电子计算机器,可以进行数值计算,又可 ...

  9. Python全栈开发

    Python全栈开发 一文让你彻底明白Python装饰器原理,从此面试工作再也不怕了. 一.装饰器 装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为“ ...

随机推荐

  1. SpringCloud笔记七:Zuul

    目录 什么是Zull 为什么需要Zuul 新建Zuul项目 运行Zuul Zuul的基本配置 忽略微服务的真实名称 设置统一公共前缀 总结 什么是Zull Zuul就是一个网关,实现的功能:代理.路由 ...

  2. 前端安全类——CSRF/XSS

    CSRF 概念:跨站请求伪造 全称:Cross-site request forgery 攻击原理:网站中某一个接口存在漏洞,用户在注册网站登录过 防御措施: 1.Token验证:引诱链接只会自动携带 ...

  3. 集智人工智能学习笔记Python#0

    1,学习基本Python语句规范: print('Hello world') print() 为函数 ‘Hello world’为字符串 2,表达式和语句的区别: 表达式有结果,运算就是表达式的一种: ...

  4. python flsak 框架

    1.flask  轻量级微型web框架 优点:微框架.简单.可扩展 将flask变量实例化到app变量中 如果想要flask自动加载修改后的代码,要app.run(debug=True) 2.路由和视 ...

  5. MySQL学习13 - 索引

    一.索引的介绍 二 .索引的作用 三.常见的几种索引: 3.1 普通索引 3.2 唯一索引 3.3 主键索引 3.4 组合索引 四.索引名词 五.正确使用索引的情况 什么是最左前缀呢? 六.索引的注意 ...

  6. Ubuntu18.04环境下melodic安装gmapping

    Ubuntu18.04 环境下melodic中很多包没有提供sudo apt install的安装方式,需要通过源代码安装,安装方法如下: 1.先安装依赖库: sudo apt--dev sudo a ...

  7. Groovy中的GString

    在讨论GString之前,我们先讨论一下Groovy里面的String.在Groovy里面String有 println 'test string' println '''test string''' ...

  8. Supervisor的安装以及使用

    1.supervisor的介绍 Supervisor 是用Python开发的一个client/server服务,是Linux/Unix系统下的一个进程管理工具,不支持Windows系统,通过配置可以实 ...

  9. sqli注入--利用information_schema配合双查询报错注入

    目录 sqli-labs 5.6双查询报错注入通关 0x01 获取目标库名 0x02 获取库中表的数量 0x03 获取库中表名 0x04 获取目标表中的列数 0x05 获取目标表的列名 0x06 从列 ...

  10. Spring框架-AOP详细学习[转载]

    参考博客:https://blog.csdn.net/qq_22583741/article/details/79589910#4-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85% ...