手写弹幕服务器—包看懂篇
手写弹幕服务器—包看懂篇
socket.io
简介
使用流行的 web 应用技术栈 —— 比如 LAMP (PHP) —— 来编写聊天应用通常是很困难的。它包含了轮询服务器以检测变化,还要追踪时间戳,并且这种实现是比较慢的。
大多数实时聊天系统通常基于 socket 来构建。 Socket 为客户端和服务器提供了双向通信机制。
这意味着服务器可以 推送 消息给客户端。无论何时你发布一条消息,服务器都可以接收到消息并推送给其他连接到服务器的客户端。
web 框架
首先要制作一个 HTML 页面来提供表单和消息列表。我们使用了基于 Node.JS 的 web 框架 express 。 请确保安装了 Node.JS。
首先创建一个 package.json 来描述我们的项目。 推荐新建一个空目录 (这里使用 chat-example)。
express 已经安装好了。我们现在新建一个 index.js 文件来创建应用。
var app = require('express')();
var http = require('http').Server(app);
app.get('/', function(req, res){
res.send('Hello world ');
});
http.listen(3000, function(){
console.log('listening on *:4000');
});
这段代码作用如下:
Express 初始化 app 作为 HTTP 服务器的回调函数。
定义了一个路由 / 来处理首页访问。
使 http 服务器监听端口 4000。
HTML 服务器
目前在 index.js 中我们是通过 res.send 返回一个 HTML 字符串。 如果我们将整个应用的 HTML 代码都放到应用代码里,代码结构将变得很混乱。 替代的方法是新建一个 index.html 文件作为服务器响应。
现在我们用 sendFile 来重构之前的回调:
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
index.html 内容如下:
Socket.IO chat
集成 Socket.IO
Socket.IO 由两部分组成:
一个服务端用于集成 (或挂载) 到 Node.JS HTTP 服务器: socket.io
一个加载到浏览器中的客户端: socket.io-client
这个两部分都会运用到
npm install --save socket.io
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
我们通过传入 http (HTTP 服务器) 对象初始化了 socket.io 的一个实例。 然后监听 connection 事件来接收 sockets, 并将连接信息打印到控制台。
在 index.html 的
标签中添加如下内容:
这样就加载了 socket.io-client。 socket.io-client 暴露了一个 io 全局变量,然后连接服务器。
请注意我们在调用 io() 时没有指定任何 URL,因为它默认将尝试连接到提供当前页面的主机。
重新加载服务器和网站,你将看到控制台打印出 “a user connected”。
每个 socket 还会触发一个特殊的 disconnect 事件:
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
触发事件
Socket.IO 的核心理念就是允许发送、接收任意事件和任意数据。任意能被编码为 JSON 的对象都可以用于传输。二进制数据 也是支持的。
这里的实现方案是,当用户输入消息时,服务器接收一个 chat message 事件。index.html 文件中的 script 部分现在应该内容如下:
广播
接下来的目标就是让服务器将消息发送给其他用户。
要将事件发送给每个用户,Socket.IO 提供了 io.emit 方法:
io.emit('some event', { for: 'everyone' });
为了简单起见,我们将消息发送给所有用户,包括发送者。
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
用法总结
服务端
io.on('connection',function(socket));
监听客户端连接,回调函数会传递本次连接的socket
io.sockets.emit('String',data);
给所有客户端广播消息
socket.broadcast.emit("msg",{data:"hello,everyone"});
给除了自己以外的客户端广播消息
io.sockets.socket(socketid).emit('String', data);
给指定的客户端发送消息
socket.on('String',function(data));
监听客户端发送的信息
socket.emit('String', data);
给该socket的客户端发送消息
io.of('/some').on('connection', function (socket) {
socket.on('test', function (data) {
socket.broadcast.emit('event_name',{});
});
});
分组
进阶——处理用户发送的数据
一、redis
什么是Redis?
REmote DIctionary Server(Redis) 是一个由SalvatoreSanfilippo写的key-value(键值对)存储系统。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是字符串(String), 哈希(Map), 列表(list), 集合(sets) 和有序集合(sorted sets)等类型。
Redis中的数据类型
哈希(Map hashmap):散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。
列表(list):列表是一种数据项构成的有限序列,即按照一定的线性顺序,排列而成的数据项的集合。(redis中使用双向链表实现)
集合(sets):和中学时学习的概念是相似的。特点是集合中元素不能重复是唯一的。切内部是无序的
有序集合(sorted sets):也是一种集合,但是内部数据是经过排序的。
redis安装
Redis 安装链接
npm redis
redis使用方法
0、建立node-redis的client端连接 npm i redis --save
// redis 链接
var redis = require('redis');
var client = redis.createClient('6379', '127.0.0.1');
// redis 链接错误
client.on("error", function(error) {
console.log(error);
});
// redis 验证 (reids.conf未开启验证,此项可不需要)
// client.auth("foobared");
module.exports = {
client:client
}
1、set的存取
const {client} = require('./redis')
client.set('key001', 'AAA', function (err, response) {
if (err) {
console.log("err:", err);
} else {
console.log(response);
client.get('key001', function (err, res) {
if (err) {
console.log("err:", err);
} else {
console.log(res);
client.end(true);
}
});
}
});
2、hash存取
hash set的设值和抽取数据都有单个key和多个key两种方式:
const {client} = require('./redis')
client.hset('filed002', 'key001', 'wherethersisadoor', function (err, res) {
if (err) {
console.log(err);
} else {
console.log('res:', res);
client.hget('filed002', 'key001', function (err, getRslt) {
if (err) {
console.log(err);
} else {
console.log('getRslt:', getRslt);
client.end(true);
}
});
}
});
注意:当hget方法在指定field下找不到指定的key时,会传给回调函数null,而非空字符或undefined。
※ 设定多个key的值,取值时获取指定field下指定单个或多个key的值
const {client} = require('./redis')
var qe = {a: 2, b:3, c:4};
client.hmset('field003', qe, function(err, response) {
console.log("err:", err);
console.log("response:", response);
client.hmget('field003', ['a', 'c'], function (err, res) {
console.log(err);
console.log(res);
client.end(true);
});
});
hmset方法的设定值可以是JSON格式的数据,但是redis中key的值是以字符串形式存储的,如果JSON数据层数超过一层,会出现值是'[object Object]'的情况。
hmget方法的返回值是个数组,其中元素的顺序对应于参数的key数组中的顺序,如果参数数组中有在field内不存在的key,返回结果数组的对应位置会是null,也即无论是否能取到值,结果数组中的元素位置始终与参数的key数组中元素位置一一对应。
获取hash中所有key的方法是client.keys(fieldname, callback); 需要注意的是如果hash中key的数目很多,这个方法的可能耗费很长时间。
3.链表 适合存储社交网站的新鲜事 lpush key value [value ...] 向链表key左边添加元素 rpush key value [value...] 向链表key右边添加元素 lpop key 移除key链表左边第一个元素 rpop key 移除key链表右边第一元素
const {client} = require('./redis')
client.lpush('test', 12345, function(err, response) {
if(err){
console.log("err:", err);
}else{
console.log("response:", response);
client.rpop('test',function (err, res){
if(err){
console.log(err);
}else{
console.log(res);
client.end(true);
}
});
}
});
[图片上传失败...(image-354cf6-1519888571721)]
socket.io中接入redis 并创建多个命名空间
How to use
const io = require('socket.io')(3000);
const redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
将index.js修改为
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const redis = require('socket.io-redis');
const {client} = require('./test/redis')
const moment = require('moment')
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.adapter(redis({host: 'localhost', port: 6379}));
var nameBox = ['/chatroom','/live','/vod','/wechat','/broadcast'];
for(var item in nameBox){
var nsp = io.of(nameBox[item])
socketMain(nsp,nameBox[item])
}
function socketMain(nsp,roomName) {
nsp.on('connection',function (socket) {
console.log('a user connected')
socket.on('disconnect', function(){
console.log('user disconnected');
});
socket.on('chat message', function(msg){
var data = {"socketid":socket.id,"cid":roomName,"msg":msg,createTime:moment().unix()};
client.lpush('message',JSON.stringify(data),redis.print)
console.log('message: ' + msg);
});
})
}
http.listen(4000, function(){
console.log('listening on *:4000');
});
index.html
var socket = io.connect("http://127.0.0.1:4000/live");
接入redis
client.lpush('message',JSON.stringify(msg),redis.print)
二、另起一个服务端拿redis数据进行处理
修改redis.js
module.exports = {
client:client,
ip:'http://127.0.0.1:4000'
}
新建sclient.js
const io = require('socket.io-client');
const async = require('async');
const moment = require('moment');
const redis = require('redis');
const {client,ip} = require('./test/redis');
const domain = require('domain');
const debug = require('debug')('socket-client:main');
var origin = io.connect(ip+'/', {reconnect: true});
var chatroom = io.connect(ip+'/chatroom', {reconnect: true});
var live = io.connect(ip+'/live', {reconnect: true});
var vod = io.connect(ip+'/vod', {reconnect: true});
var wechat = io.connect(ip+'/wechat', {reconnect: true});
var broadcast = io.connect(ip+'/broadcast', {reconnect: true});
var namBox = {root:origin,chatroom:chatroom,live:live,vod:vod,wechat:wechat,broadcast:broadcast};
var reqDomain = domain.create();
reqDomain.on('error', function (err) {
console.log(err);
try {
var killTimer = setTimeout(function () {
process.exit(1);
}, 100);
killTimer.unref();
} catch (e) {
console.log('error when exit', e.stack);
}
});
reqDomain.run(function () {
compute();
});
process.on('uncaughtException', function (err) {
console.log(err);
try {
var killTimer = setTimeout(function () {
process.exit(1);
}, 100);
killTimer.unref();
} catch (e) {
console.log('error when exit', e.stack);
}
});
function compute() {
client.llen('message', function(error, count){
if(error){
console.log(error);
}else{
if(count){
//console.log('-------------has count',time);
popLogs();
process.nextTick(compute);
}else{
//console.log('-------------empty',time);
setTimeout(function(){
compute();
},100);
}
}
});
}
function popLogs(){
var time = moment().unix();
console.log('-------------dealStart-------------',time);
client.rpop('message',function(err,result){
if(err){
console.log(err);
}else{
var result = JSON.parse(result);
try{
var cid = result.cid;
//console.log('place',result.place);
}catch(e){
console.log('empty data cid',result);
return;
}
console.log(' start '+' nsp: '+cid +' time: '+time);
if(namBox[cid]){
console.log(result);
namBox[cid].emit('redisCome',result);
}
}
});
}
修改index.js 增加redisCome监听事件
/*接收redis发来的消息*/
socket.on('redisCome',function (data) {
console.log('-------------redisCome',data.msg);
try{
var msg = data.msg
}catch(e){
var msg = '';
}
console.log(data);
nsp.emit('message.add',msg);
});
修改index.html
socket.on('message.add',function (msg) {
$('#messages').append($('').text(msg));
})
三、增加用户发送信息校验
增加信息的安全性,我们可以对用户发送的信息进行敏感词、sql注入攻击、xss攻击等进行过滤 使用async一步步操作流程
修改sclient.js
async.waterfall([
function (done) {
user.messageDirty({msg:result.msg},function(err,res){
//console.log('sql done'/*,res*/);
done(err,res);
});
},
function (res,done) {
user.messageValidate({msg:result.msg},function(err,res){
//console.log('key done'/*,res*/);
done(err,res);
});
}
],function (err,res) {
if(err){
console.log('err!!!!',err,result);
namBox[cid].emit('messageError',err);
}else{
if(namBox[cid]) {
console.log(result);
namBox[cid].emit('redisCome', result);
}
}
})
修改index.js
/*接收redis错误信息返回*/
socket.on('messageError',function(err){
console.log('messageError');
try{
nsp.emit('message.error',err.msg);
}catch(e){
}
});
修改index.html
mysql入库
1.在本地安装mysql数据库 2.下载node mysql包
npm install mysql --save
3.连接数据库 建立连接池
var mysql = require('mysql');
var pool = mysql.createPool({
host: 'localhost',
user:'root',
password:'123456',
database : 'danmaku'
});
var query = function(sql,options,callback){
pool.getConnection(function(err,conn){
if(err){
callback(err,null,null);
}else{
conn.query(sql,options,function(err,results,fields){
//释放连接
conn.release();
//事件驱动回调
callback(err,results,fields);
});
}
});
};
新建query.js
var {query} = require("./test/redis");
query("select * from demo", function(err,results,fields){
//do something
if(err){
console.log(err)
}else {
console.log(results)
}
});
新建insert.js
var {query} = require("./test/redis");
const moment = require('moment')
query('insert into demo(message,createTime) values(?,?)',[123,moment().unix()],function(err,results,fields){
//do something
if(err){
console.log(err)
}else {
console.log(results)
}
});
mysql -u root -p use danmaku; select * from demo;
4.在程序中添加入库步骤
弹幕播放器
ABPlayerHTML5
你可能感兴趣的:(手写弹幕服务器—包看懂篇)
网络分析工具-tcpdump
锅锅来了
Linux性能优化原理和实战 tcpdump php 网络 网络协议 疑难杂症
文章目录前言一、tcpdump基础官网链接命令选项详解常规过滤规则tcpdump输出一、tcpdump实践HTTP协议ICMP状态抓包前言当遇到网络疑难问题的时候,抓包是最基本的技能,通过抓包才能看到网络底层的问题一、tcpdump基础tcpdump是一个常用的网络分析工具。它基于libpcap,利用内核中的AF_PACKET套接字,抓取网络接口中传输的网络包。我们对网卡进行抓包的时候,会使得网卡
头歌解答 初识Redis
Rozen_a
redis 数据库 nosql
第1关:Redis中的数据结构编程要求根据提示,打开命令行,启动Redis客户端并创建一些值:使用默认配置后台启动Redis服务器启动Redis客户端redis-cli设置字符串键为hello值为redis设置列表,键为educoder-list从列表左侧推入元素hello从列表右侧推入元素educoder从列表右侧推入元素bye从列表右侧弹出一个元素设置集合,键为educoder-set添加元素
代码随想录打卡第五十一天
zengy5
代码随想录刷题流程 深度优先 算法 图论 c++ leetcode
代码随想录–图论部分day51图论第二天文章目录代码随想录--图论部分一、卡码网99--岛屿数量二、卡码网100--岛屿的最大面积一、卡码网99–岛屿数量代码随想录题目链接:代码随想录给定一个由1(陆地)和0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。没太看懂教程的解法,所以这里是自己的做法正常把图存进来,遍历
anaconda中的python在pycharm中用不了_Pycharm中使用Anaconda
白白前
Pycharm中使用Anaconda问题:安装完Pycharm和Anaconda后,想让Pycharm能调用Anaconda中包含的各种包。这样就不用重复安装各种包了。Anaconda下载安装Anaconda指的是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项。因为包含了大量的科学包,Anaconda的下载文件比较大(约515MB)。安装Anacond
JavaEE进阶知识学习-----定时任务调度Quartz-4
四川码匠
Quartz JAVA进阶学习 Quartz 任务调度
Quartz和SpringMVC,Spring整合1.Quartz依赖的包如下:org.springframeworkspring-context-support${spring.version}org.springframeworkspring-tx${spring.version}org.quartz-schedulerquartz2.2.3使用Quartz配置作业的方式第一种:MethodI
Go Web 开发基础:从入门到实战
一小路一
掌握 Go 语言:编程世界的进阶钥匙 golang 前端 面试 后端 服务器
GoWeb开发基础:从入门到实战Go语言因其高效性和简洁性,成为了后端开发的热门选择之一。Go的net/http包提供了强大的Web服务功能,可以帮助我们快速搭建Web应用。本文将带领你从基础开始,逐步了解如何使用Go创建Web服务、处理路由、使用模板引擎、提供静态文件服务,并与数据库进行交互。文章内容包含常见的错误示例和面试题,帮助你更好地理解GoWeb开发。1.使用net/http创建一个简单
如何设置内网IP的端口映射到公网
天才技术宅
智能路由器 网络
在现代网络环境中,端口映射(PortMapping)是一项非常实用的技术,它允许用户将内网设备的服务端口映射到公网,使外网用户可以访问内网中的服务。这项技术在远程办公、设备远程控制、游戏服务器、家庭监控等场景中得到了广泛应用。今天,我们将介绍如何实现端口映射,帮助大家在不同网络环境下实现内网设备的公网访问。一、端口映射是什么?端口映射(PortMapping),也称为端口转发(PortForwar
【核心算法篇十三】《DeepSeek自监督学习:图像补全预训练方案》
再见孙悟空_
「2025 DeepSeek技术全景实战」 算法 学习 计算机视觉 deepSeek 深度学习 transformer 人工智能
引言:为什么自监督学习成为AI新宠?在传统监督学习需要海量标注数据的困境下,自监督学习(Self-SupervisedLearning)凭借无需人工标注的特性异军突起。想象一下,如果AI能像人类一样通过观察世界自我学习——这正是DeepSeek图像补全方案的技术哲学。根据,自监督学习通过设计巧妙的"预训练任务"(PretextTask),让模型在无标签数据中自动学习图像语义特征。而图像补全正是这类
全网最全!DeepSeek 新手入门教程合集
人工智能deepseek
如果你是初次接触DeepSeek的普通用户或开发者,面对海量教程却无从下手?别担心!本文为你整理全网最易懂、最实用的DeepSeek学习资源,涵盖快速上手、编程实战、系统手册等,附直达链接,收藏这一篇就够了!一、快速入门指南《DeepSeek入门教程》-博客园亮点:手把手教你注册账号、获取APIKey,并提供Python调用多轮对话的代码示例,适合初级开发者。直达链接:点击查看核心内容:API调用
集中式架构vs分布式架构
谦亨有终
架构 架构 分布式
一、集中式架构如何准确理解集中式架构1.集中式架构的定义集中式架构是一种将系统的所有计算、存储、数据处理和控制逻辑集中在一个或少数几个节点上运行的架构模式。这些中央节点(服务器或主机)作为系统的核心,负责处理所有用户请求和业务逻辑,客户端只负责请求和展示。2.核心特性单一控制中心:所有服务和资源都由中央节点统一管理。资源集中管理:数据和计算资源位于同一位置,便于维护和扩展。高一致性:由于资源集中管
Linux操作系统:个人云存储服务搭建开发
暮雨哀尘
Linux的那点事 linux 运维 服务器 大数据 集群技术 nginx mysql
个人云存储服务搭建开发文档一、项目目标搭建一个类似Dropbox的个人云存储服务,实现文件的同步和备份功能,确保数据的安全性和便捷性。二、技术栈操作系统:Linux(推荐使用UbuntuServer或CentOS)云存储软件:Nextcloud或SeafileWeb服务器:Apache或Nginx数据库:MySQL或MariaDBSSL证书:自签名证书或Let'sEncrypt免费证书三、搭建步骤
Tomcat 8 安装包下载
m0_74824517
面试 学习路线 阿里巴巴 tomcat java
Tomcat8安装包下载【下载地址】Tomcat8安装包下载本仓库提供了一个包含Windows和Linux版本的Tomcat8安装包,方便用户快速下载并部署Tomcat8服务器[这里是图片001]项目地址:https://gitcode.com/open-source-toolkit/fda7c简介本仓库提供了一个包含Windows和Linux版本的Tomcat8安装包,方便用户快速下载并部署To
Ubuntu22.4.03服务器版安装及搭建深度学习环境的问题总结
蜡笔小祎在线学习
问题集合 深度学习 人工智能
Ubuntu22.4.03服务器版安装流程整个流程已经有很多分享帖了,这里概述一下:下载iso制作启动U盘,按f2进入安装,选择语言,键盘布局english,ubuntuserver安装,DHCP自动配置网络(问题1),代理服务器我们没填,配置阿里云镜源http://mirrors.aliyun.com/ubuntu/,磁盘分区(问题2),设置服务器密码,安装ssh远程工具,重启reboot。可参
猎板 PCB:HDI 技术精要解读
lboyj
人工智能
HDI技术凭借增加盲埋孔的方式,达成了高密度布局,在高端服务器、智能手机、多功能POS机以及安防摄像机等诸多领域均有广泛应用。尤其在通讯和计算机行业中,对HDI线路板有着较高的需求,这在一定程度上有力地推动了科技的持续进步,使得HDI板在国内市场展现出十分乐观的发展前景。然而,HDI技术作为一种特殊工艺,也面临诸多挑战。一方面,其成本相对较高;另一方面,对制造商的生产能力有着严格要求。倘若缺乏先进
国鑫DeepSeek 671B本地部署方案:以高精度、高性价比重塑AI推理新标杆
Gooxi国鑫
人工智能 服务器
随着DeepSeek大模型应用火爆全球,官方服务器总是被挤爆。而且基于企业对数据安全、网络、算力的更高需求,模型本地化部署的需求日益增长,如何在有限预算内实现高效、精准的AI推理能力,成为众多企业的核心诉求。国鑫作为深耕AI领域的技术先锋,推出基于4台48GRTX4090或8台24GRTX4090服务器的2套DeepSeek“满血”版本地部署方案,以FP16高精度、高性价比、强扩展性三大优势,为企
Linux:从入门到精通的全面指南
dbsnc1111
linux 运维 服务器
一、引言Linux作为一种开源操作系统,犹如一座技术宝库,在当今的科技领域中占据着至关重要的地位。它以其卓越的稳定性、高度的安全性和无与伦比的灵活性,在服务器、嵌入式系统、个人计算机、超级计算机等众多领域广泛应用。无论是渴望提升技术水平的个人,还是寻求拓展职业道路的专业人士,学习Linux都无疑是开启新机遇之门的钥匙。以下是关于Linux的详细知识以及学习Linux的经验总结,希望能为正在学习或准
Linux-GlusterFS操作子卷
DC_BLOG
Linux linux wpf 运维 服务器 分布式
文章目录分布式卷添加卷分布式卷删除子卷删除总卷作者主页:点击!Linux专栏:点击!⏰️创作时间:2025年02月20日19点30分分布式卷添加卷Node1上进行操作扩容#服务器端glustervolumeadd-brickgv-disNode3:/exp/vdb1/brick#在分布式卷中添加卷glustervolumeinfogv-dis#之后查看分布式卷的详细信息之后就会发现新增了Node3
ffmpeg-python安装
neverayever
计算机 ffmpeg python linux
centos-ffmpeg-python安装安装ffmpeg一:下载并解压wgethttp://www.ffmpeg.org/releases/ffmpeg-4.2.tar.gztar-zxvfffmpeg-4.2.tar.gz若linux服务器没网,可以在windows上直接访问http://www.ffmpeg.org/releases/ffmpeg-4.2.tar.gz就可下载,然后上传至服
PHP 网络编程介绍
来恩1003
PHP 从入门到精通 php 网络 开发语言
PHP学习资料PHP学习资料PHP学习资料在当今数字化时代,网络编程是开发各类应用必不可少的技能。PHP作为一门广泛应用于Web开发的编程语言,同样具备强大的网络编程能力。接下来,我们将深入探讨PHP中网络连接的建立、Socket编程、HTTP请求与响应等网络相关的操作。一、网络连接的建立在PHP中建立网络连接,主要是通过使用内置的函数来实现与远程服务器的通信。最常见的是使用fsockopen函数
PHP 安全与加密:守护 Web 应用的基石
来恩1003
PHP 从入门到精通 php 安全 前端
PHP学习资料PHP学习资料PHP学习资料在当今数字化时代,Web应用无处不在,而PHP作为一种广泛使用的服务器端脚本语言,承载着无数网站和应用的核心逻辑。然而,随着网络攻击手段日益复杂,PHP应用面临着诸多安全威胁,如SQL注入、XSS攻击等,同时,数据的加密保护也至关重要。本文将深入探讨PHP中的安全问题及加密算法的应用,帮助开发者构建更安全可靠的Web应用。一、PHP安全之殇——SQL注入攻
C++ 一篇读懂“值传递”和“地址传递”
xzal12
C++ c++
让我们通过一个简单的、形象的比喻来帮助你理解“值传递”和“地址传递”是如何影响实参的。1.值传递想象你有一个**信封**(代表变量),里面放着一张纸条(代表数据)。你决定把这个信封寄给一个朋友,让他们看一下纸条的内容。-**过程**:你把信封寄给朋友,但你实际上给朋友的是一个**副本**,也就是你将信封和纸条的内容完全复制了一份。-**结果**:你的朋友可以看到纸条上的内容,但他们修改纸条内容时,
TT无人机零散笔记
xzal12
TT无人机 无人机 笔记
TT扩展板上传模式:sdk:软件开发工具包。一键安装驱动:扩展模块使用Mind+编程是通过USB串口,因此在首次使用Mind+连接扩展模块时需要一键安装驱动。恢复设备初始设置:由于扩展模块可编程,如果扩展模块中存在程序则会导致实时模式的控制无法生效,因此在使用实时模式前需要将扩展模块恢复默认固件。serial.begin(9600)#初始化串口通信,设置数据传输速率(波特率)为9600。波特率:表
第26篇:pFedLoRA: Model-Heterogeneous Personalized Federated Learning with LoRA使用lora微调的模型异构个性化联邦学习
还不秃顶的计科生
联邦学习 深度学习 人工智能 开发语言
第一部分:解决的问题联邦学习(FederatedLearning,FL)是一种分布式机器学习方法,允许客户端在本地数据上训练模型,同时通过中心服务器共享学习成果。传统FL框架假设客户端使用相同的模型结构(模型同构),但在实际中可能面对:统计异质性:客户端的数据分布不均(non-IID)。资源异质性:客户端硬件资源有限。模型异质性:客户端可能拥有不同的模型结构。模型异构的个性化联邦学习(MHPFL)
vue中使用ueditor上传到服务器_vue+Ueditor集成 [前后端分离项目][图片、文件上传][富文本编辑]...
小西超人
写在最前面的话:鉴于近期很多的博友讨论,说我按照文章的一步一步来,弄好之后,怎么会提示后端配置项http错误,文件上传会提示上传错误。这里提别申明一点,ueditor在前端配置好后,需要与后端部分配合进行,后端部分的项目代码git地址:https://github.com/coderliguoqing/UeditorSpringboot,然后将配置ueditor.config.js里的server
记录App中加入Mqtt实现过程
街角的小菜鸟
Android开发
前言因为公司项目里因为功能的修改,移除了关于无人机飞控控制的代码部分,软件中无人机信息变更为通过mqtt获取,通过翻阅网上资料后,终于实现了该功能。现在写下来,以免再次用到要重新查找资料。MQTT的相关了解Topic:订阅的主题。URI:MQTT服务器的地址例如:"tcp://"+MQTT_HOST+":"+MQTT_PORTusername&password:账户与密码ClientId:客户端的
前后端分离跨域问题解决方案
慕容屠苏
大前端爬坑之路 前后端分离 跨域问题解决方案
前后端分离跨域问题解决方案现在的web开发中经常会用到前后分离技术,前后端分解技术,都会涉及到跨域问题。解决跨域问题的方法:第一种解决方案jsonp(不推荐使用)这种方案其实我是不赞同的,第一,在编码上jsonp会单独因为回调的关系,在传入传出还有定义回调函数上都会有编码的”不整洁”.简单阐述jsonp能够跨域是因为javascript的script标签,通过服务器返回script标签的code,
ptython setup.py install 设置python包编译时的并行数
leo0308
基础知识 Python python pytorch3d
通过源码编译安装pytorch3d的时候,直接执行pythonsetup.pyinstall时,默认开的并行数很多,有10几个,直接导致机器卡死。通过设置下面的环境变量,可以设置较小的并行数,避免占用过多的资源。exportMAX_JOBS=4设置后,同时只有4个编译的进程。
AJAX使用和固定格式
乐多_L
ajax 前端 javascript
ajax的全称AsynchronousJavaScriptandXML(异步JavaScript和XML)。ajax是一种创建交互式网页应用的网页开发技术。其中最核心的依赖是浏览器提供的XMLHttpRequest对象,是这个对象使得浏览器可以发出HTTP请求与接收HTTP响应。实现了在页面不刷新的情况下和服务器进行交互。方法描述newXMLHttpRequest()生成一个XMLHttpRequ
YOLOv8到YOLOv11:深度解析目标检测架构的演进
金外飞176
技术前沿 目标跟踪 人工智能 计算机视觉 目标检测 YOLO 神经网络 深度学习
YOLOv8到YOLOv11:深度解析目标检测架构的演进在计算机视觉领域,YOLO(YouOnlyLookOnce)系列模型一直是实时目标检测领域的佼佼者。从2015年的YOLOv1到2024年的YOLOv11,这一系列模型经历了快速的迭代和发展,不断刷新着目标检测的性能和效率。然而,由于部分YOLO版本缺乏详细的学术论文和架构图,研究人员和开发者在理解这些模型的工作原理时往往面临挑战。最近,一篇
详细介绍:封装简易的 Axios 函数获取省份列表
还是鼠鼠
javascript vscode ajax 前端 前端框架
目录关键步骤:完整代码(html):代码解析:程序运行结果:本示例展示了如何通过封装一个简易的myAxios函数来模拟axios的功能,使用原生的XMLHttpRequest(XHR)对象来发起HTTP请求。我们将实现一个简单的功能,通过该封装函数从服务器获取省份列表数据,并在网页上显示这些省份。关键步骤:封装myAxios函数:myAxios函数接收一个配置对象(如请求的URL和方法),并返回一
多线程编程之理财
周凡杨
java 多线程 生产者 消费者 理财
现实生活中,我们一边工作,一边消费,正常情况下会把多余的钱存起来,比如存到余额宝,还可以多挣点钱,现在就有这个情况:我每月可以发工资20000万元 (暂定每月的1号),每月消费5000(租房+生活费)元(暂定每月的1号),其中租金是大头占90%,交房租的方式可以选择(一月一交,两月一交、三月一交),理财:1万元存余额宝一天可以赚1元钱,
[Zookeeper学习笔记之三]Zookeeper会话超时机制
bit1129
zookeeper
首先,会话超时是由Zookeeper服务端通知客户端会话已经超时,客户端不能自行决定会话已经超时,不过客户端可以通过调用Zookeeper.close()主动的发起会话结束请求,如下的代码输出内容
Created /zoo-739160015
CONNECTEDCONNECTED
.............CONNECTEDCONNECTED
CONNECTEDCLOSEDCLOSED
SecureCRT快捷键
daizj
secureCRT 快捷键
ctrl + a : 移动光标到行首ctrl + e :移动光标到行尾crtl + b: 光标前移1个字符crtl + f: 光标后移1个字符crtl + h : 删除光标之前的一个字符ctrl + d :删除光标之后的一个字符crtl + k :删除光标到行尾所有字符crtl + u : 删除光标至行首所有字符crtl + w: 删除光标至行首
Java 子类与父类这间的转换
周凡杨
java 父类与子类的转换
最近同事调的一个服务报错,查看后是日期之间转换出的问题。代码里是把 java.sql.Date 类型的对象 强制转换为 java.sql.Timestamp 类型的对象。报java.lang.ClassCastException。
代码:
可视化swing界面编辑
朱辉辉33
eclipse swing
今天发现了一个WindowBuilder插件,功能好强大,啊哈哈,从此告别手动编辑swing界面代码,直接像VB那样编辑界面,代码会自动生成。
首先在Eclipse中点击help,选择Install New Software,然后在Work with中输入WindowBui
web报表工具FineReport常用函数的用法总结(文本函数)
老A不折腾
finereport web报表工具 报表软件 java报表
文本函数
CHAR
CHAR(number):根据指定数字返回对应的字符。CHAR函数可将计算机其他类型的数字代码转换为字符。
Number:用于指定字符的数字,介于1Number:用于指定字符的数字,介于165535之间(包括1和65535)。
示例:
CHAR(88)等于“X”。
CHAR(45)等于“-”。
CODE
CODE(text):计算文本串中第一个字
mysql安装出错
林鹤霄
mysql安装
[root@localhost ~]# rpm -ivh MySQL-server-5.5.24-1.linux2.6.x86_64.rpm Preparing... #####################
linux下编译libuv
aigo
libuv
下载最新版本的libuv源码,解压后执行:
./autogen.sh
这时会提醒找不到automake命令,通过一下命令执行安装(redhat系用yum,Debian系用apt-get):
# yum -y install automake
# yum -y install libtool
如果提示错误:make: *** No targe
中国行政区数据及三级联动菜单
alxw4616
近期做项目需要三级联动菜单,上网查了半天竟然没有发现一个能直接用的!
呵呵,都要自己填数据....我了个去这东西麻烦就麻烦的数据上.
哎,自己没办法动手写吧.
现将这些数据共享出了,以方便大家.嗯,代码也可以直接使用
文件说明
lib\area.sql -- 县及县以上行政区划分代码(截止2013年8月31日)来源:国家统计局 发布时间:2014-01-17 15:0
哈夫曼加密文件
百合不是茶
哈夫曼压缩 哈夫曼加密 二叉树
在上一篇介绍过哈夫曼编码的基础知识,下面就直接介绍使用哈夫曼编码怎么来做文件加密或者压缩与解压的软件,对于新手来是有点难度的,主要还是要理清楚步骤;
加密步骤:
1,统计文件中字节出现的次数,作为权值
2,创建节点和哈夫曼树
3,得到每个子节点01串
4,使用哈夫曼编码表示每个字节
JDK1.5 Cyclicbarrier实例
bijian1013
java thread java多线程 Cyclicbarrier
CyclicBarrier类
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环的 barrier。
CyclicBarrier支持一个可选的 Runnable 命令,
九项重要的职业规划
bijian1013
工作 学习
一. 学习的步伐不停止 古人说,活到老,学到老。终身学习应该是您的座右铭。 世界在不断变化,每个人都在寻找各自的事业途径。 您只有保证了足够的技能储
【Java范型四】范型方法
bit1129
java
范型参数不仅仅可以用于类型的声明上,例如
package com.tom.lang.generics;
import java.util.List;
public class Generics<T> {
private T value;
public Generics(T value) {
this.value =
【Hadoop十三】HDFS Java API基本操作
bit1129
hadoop
package com.examples.hadoop;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoo
ua实现split字符串分隔
ronin47
lua split
LUA并不象其它许多"大而全"的语言那样,包括很多功能,比如网络通讯、图形界面等。但是LUA可以很容易地被扩展:由宿主语言(通常是C或 C++)提供这些功能,LUA可以使用它们,就像是本来就内置的功能一样。LUA只包括一个精简的核心和最基本的库。这使得LUA体积小、启动速度快,从 而适合嵌入在别的程序里。因此在lua中并没有其他语言那样多的系统函数。习惯了其他语言的字符串分割函
java-从先序遍历和中序遍历重建二叉树
bylijinnan
java
public class BuildTreePreOrderInOrder {
/**
* Build Binary Tree from PreOrder and InOrder
* _______7______
/ \
__10__ ___2
/ \ /
4
openfire开发指南《连接和登陆》
开窍的石头
openfire 开发指南 smack
第一步
官网下载smack.jar包
下载地址:http://www.igniterealtime.org/downloads/index.jsp#smack
第二步
把smack里边的jar导入你新建的java项目中
开始编写smack连接openfire代码
p
[移动通讯]手机后盖应该按需要能够随时开启
comsci
移动
看到新的手机,很多由金属材质做的外壳,内存和闪存容量越来越大,CPU速度越来越快,对于这些改进,我们非常高兴,也非常欢迎
但是,对于手机的新设计,有几点我们也要注意
第一:手机的后盖应该能够被用户自行取下来,手机的电池的可更换性应该是必须保留的设计,
20款国外知名的php开源cms系统
cuiyadll
cms
内容管理系统,简称CMS,是一种简易的发布和管理新闻的程序。用户可以在后端管理系统中发布,编辑和删除文章,即使您不需要懂得HTML和其他脚本语言,这就是CMS的优点。
在这里我决定介绍20款目前国外市面上最流行的开源的PHP内容管理系统,以便没有PHP知识的读者也可以通过国外内容管理系统建立自己的网站。
1. Wordpress
WordPress的是一个功能强大且易于使用的内容管
Java生成全局唯一标识符
darrenzhu
java uuid unique identifier id
How to generate a globally unique identifier in Java
http://stackoverflow.com/questions/21536572/generate-unique-id-in-java-to-label-groups-of-related-entries-in-a-log
http://stackoverflow
php安装模块检测是否已安装过, 使用的SQL语句
dcj3sjt126com
sql
SHOW [FULL] TABLES [FROM db_name] [LIKE 'pattern']
SHOW TABLES列举了给定数据库中的非TEMPORARY表。您也可以使用mysqlshow db_name命令得到此清单。
本命令也列举数据库中的其它视图。支持FULL修改符,这样SHOW FULL TABLES就可以显示第二个输出列。对于一个表,第二列的值为BASE T
5天学会一种 web 开发框架
dcj3sjt126com
Web 框架 framework
web framework层出不穷,特别是ruby/python,各有10+个,php/java也是一大堆 根据我自己的经验写了一个to do list,按照这个清单,一条一条的学习,事半功倍,很快就能掌握 一共25条,即便很磨蹭,2小时也能搞定一条,25*2=50。只需要50小时就能掌握任意一种web框架
各类web框架大同小异:现代web开发框架的6大元素,把握主线,就不会迷路
建议把本文
Gson使用三(Map集合的处理,一对多处理)
eksliang
json gson Gson map Gson 集合处理
转载请出自出处:http://eksliang.iteye.com/blog/2175532 一、概述
Map保存的是键值对的形式,Json的格式也是键值对的,所以正常情况下,map跟json之间的转换应当是理所当然的事情。 二、Map参考实例
package com.ickes.json;
import java.lang.refl
cordova实现“再点击一次退出”效果
gundumw100
android
基本的写法如下:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
//navigator.splashscreen.hide();
document.addEventListener("b
openldap configuration leaning note
iwindyforest
configuration
hostname // to display the computer name
hostname <changed name> // to change
go to: /etc/sysconfig/network, add/modify HOSTNAME=NEWNAME to change permenately
dont forget to change /etc/hosts
Nullability and Objective-C
啸笑天
Objective-C
https://developer.apple.com/swift/blog/?id=25
http://www.cocoachina.com/ios/20150601/11989.html
http://blog.csdn.net/zhangao0086/article/details/44409913
http://blog.sunnyxx
jsp中实现参数隐藏的两种方法
macroli
JavaScript jsp
在一个JSP页面有一个链接,//确定是一个链接?点击弹出一个页面,需要传给这个页面一些参数。//正常的方法是设置弹出页面的src="***.do?p1=aaa&p2=bbb&p3=ccc"//确定目标URL是Action来处理?但是这样会在页面上看到传过来的参数,可能会不安全。要求实现src="***.do",参数通过其他方法传!//////
Bootstrap A标签关闭modal并打开新的链接解决方案
qiaolevip
每天进步一点点 学习永无止境 bootstrap 纵观千象
Bootstrap里面的js modal控件使用起来很方便,关闭也很简单。只需添加标签 data-dismiss="modal" 即可。
可是偏偏有时候需要a标签既要关闭modal,有要打开新的链接,尝试多种方法未果。只好使用原始js来控制。
<a href="#/group-buy" class="btn bt
二维数组在Java和C中的区别
流淚的芥末
java c 二维数组 数组
Java代码:
public class test03 {
public static void main(String[] args) {
int[][] a = {{1},{2,3},{4,5,6}};
System.out.println(a[0][1]);
}
}
运行结果:
Exception in thread "mai
systemctl命令用法
wmlJava
linux systemctl
对比表,以 apache / httpd 为例 任务 旧指令 新指令 使某服务自动启动 chkconfig --level 3 httpd on systemctl enable httpd.service 使某服务不自动启动 chkconfig --level 3 httpd off systemctl disable httpd.service 检查服务状态 service h