当前位置: 首页 > news >正文

C#与php自定义数据流传输

C#与php自定义数据流传输

  • 介绍
  • 一、客户端与服务器数据传输流程图
    • 客户端发送数据给服务器:
    • 服务器返回数据给客户端:
  • 二、自定义数据流
    • C#版本数据流
    • PHP版本数据流
  • 三、数据传输测试
    • 1.在Unity中创建一个C#脚本NetWorkManager.cs
    • 2.服务器www目录创建StreamTest.php脚本代码如下:
    • 结果如下:
    • 这里需要注意一个问题,自定义数据类写入过程和读取过程顺序必须一致,否则无法获取数据。
    • PHP中的pack与unpack的方法将数据转换为二进制的方法最好了解下。

介绍

如果不了解Unity与web如何通讯的可以看我之前的文章。
无论传输什么类型的数据,如int、float、string等,他们都被保存在文本中,接下来我们从字符串中解析这些数据。

一、客户端与服务器数据传输流程图

客户端发送数据给服务器:

在这里插入图片描述

服务器返回数据给客户端:

在这里插入图片描述

二、自定义数据流

C#版本数据流

我们要创建一个C#版本的数据流类,它的主要功能是将各种不同类型的数据压入一个单独的字符创中,或将从服务器读回的字节数组解析成响应的数据,这里要清楚不同类型数据所占字节长度,如32位int即占用4个字节,短整型short占2个字节等,代码如下:

using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;public class PostStream {public Dictionary<string,string> Headers = new Dictionary<string, string>();const int HASHSIZE = 16;        //末尾16个字节保存md5数字签名const int BYTE_LEN = 1;         //byte占一个字节const int SHORT16_LEN = 2;      //short占2个字节const int INT32_LEN = 4;        //int占4个字节const int FLOAT_LEN = 4;        //float占4个字节private int m_index = 0;public int Length{get{return m_index;}}//秘密密码,用于数字签名private string m_secretKey = "123456";//存储Post信息private string[,] m_field;/// <summary>/// 最大传输数量/// </summary>private const int MAX_POST = 128;/// <summary>/// 单位Post信息所存储的信息量/// </summary>private const int PAIR = 2;/// <summary>/// 信息头索引/// </summary>private const int HEAD = 0;/// <summary>/// 信息内容索引/// </summary>private const int CONTENT = 1;/// <summary>/// 收到的字节数组/// </summary>private byte[] m_bytes = null;public byte[] BYTES { get { return m_bytes; } }/// <summary>/// 发送的字符串/// </summary>private string m_content = "";/// <summary>/// 读取是否出现错误/// </summary>private bool m_errorRead = false;/// <summary>/// 是否进行数字签名/// </summary>private bool m_sum = true;/// <summary>/// 构造函数初始化/// </summary>public PostStream(){Headers = new Dictionary<string,string>();m_index = 0;m_bytes = null;m_content = "";m_errorRead = false;}//这个类的第一部分是将不同类型的数据按POST格式压入到m_content字符串和二位字符串数组m_field中。m_content中的数据时实际发送的数据,m_field中的数据用于MD5数字签名。#region 写入数据/// <summary>/// 开始压数据,issum参数用来标识是否进行MD5数字签名/// </summary>public void BeginWrite(bool issum){m_index = 0;m_sum = issum;m_field = new string[MAX_POST, PAIR];Headers.Add("Content-Type", "application/x-www-form-urlencoded");}/// <summary>/// head表示POST的名字,content是实际的数据内容/// </summary>/// <param name="head"></param>/// <param name="content"></param>public void Write(string head, string content){if (m_index >= MAX_POST) return;m_field[m_index, HEAD] = head;m_field[m_index, CONTENT] = content;m_index++;if (m_content.Length == 0)m_content += (head + "=" + content);elsem_content += ("&" + head + "=" + content);Debug.LogError(m_content);}/// <summary>/// 使用MD5对字符串进行数字签名/// </summary>public void EndWrite(){if (m_sum){string hasstring = "";for (int i = 0; i < MAX_POST; i++)hasstring += m_field[i, CONTENT];hasstring += m_secretKey; //数据: content1content2...m_secretKeyDebug.LogError("hasstring=" + hasstring);m_content += "&key=" + Md5Sum(hasstring);//数据: head1=content1&head2=content2...&key=(hasstring的MD5值)Debug.LogError("m_content=" + m_content);}m_bytes = Encoding.UTF8.GetBytes(m_content);}#endregion//第二部分是读取从服务器返回的数据。从服务器返回的数据时一个单独的字节数组,我们将这个数组解析为相应的数据,这个过程用到了最多的是BitConverter函数,它可以将相应长度的字节转为对应的数据#region 读取数据/// <summary>/// 读取数据/// </summary>/// <param name="www"></param>/// <param name="issum"></param>/// <returns></returns>public bool BeginRead(WWW www,bool issum){m_bytes = www.bytes;m_content = www.text;m_sum = issum;//错误if (m_bytes == null){m_errorRead = true;return false;}//读取前2个字节,获得字符串长度short length = 0;this.ReadShort(ref length);//服务器这里做了处理,在写入数据时先写入一个short类型的数据代表数据长度if (length != m_bytes.Length){m_index = length;m_errorRead = true;return false;}//比较本地与服务器数字签名是否一致if (m_sum){byte[] localhash = GetLocalHash(m_bytes, m_secretKey);byte[] hashbytes = GetCurrentHash(m_bytes);if (!ByteEquals(localhash,hashbytes)){m_errorRead = true;return false;}}return true;}/// <summary>/// 忽略一个字节/// </summary>public void IgnoreByte(){if (m_errorRead) return;m_index += BYTE_LEN;}/// <summary>/// 读取一个字节/// </summary>public void ReadByte(ref byte bts){if (m_errorRead) return;bts = m_bytes[m_index];m_index += BYTE_LEN;}/// <summary>/// 读取一个short/// </summary>/// <param name="number"></param>public void ReadShort(ref short number){if (m_errorRead) return;number = System.BitConverter.ToInt16(m_bytes,m_index);m_index += SHORT16_LEN;}/// <summary>/// 读取一个int/// </summary>public void ReadInt(ref int number){if (m_errorRead) return;number = System.BitConverter.ToInt32(m_bytes,m_index);m_index += INT32_LEN;}/// <summary>/// 读取一个float/// </summary>public void ReadFloat(ref float number){if (m_errorRead) return;number = System.BitConverter.ToSingle(m_bytes, m_index);m_index += FLOAT_LEN;}/// <summary>/// 读取一个字符串/// </summary>public void ReadString(ref string str){if (m_errorRead) return;short num = 0;ReadShort(ref num);str = Encoding.UTF8.GetString(m_bytes,m_index,(int)num);m_index += num;}/// <summary>/// 读取一个bytes数组/// </summary>/// <param name="bytes"></param>public void ReadBytes(ref byte[] bytes){if (m_errorRead) return;short len = 0;ReadShort(ref len);//字节流bytes = new byte[len];for (int i = m_index; i < m_index + len; i++){bytes[i - m_index] = m_bytes[i];}m_index += len;}/// <summary>/// 结束读取/// </summary>/// <returns></returns>public bool EndRead(){if (m_errorRead) return false;else return true;}#endregion/// <summary>/// 去掉服务器返回的数字签名,使用本地秘钥重新计算数字签名/// </summary>/// <returns></returns>public static byte[] GetLocalHash(byte[] bytes,string key){//hash bytesbyte[] hashbytes = null;int n = bytes.Length - HASHSIZE;if (n < 0) return hashbytes;//获得key的bytesbyte[] keybytes = System.Text.ASCIIEncoding.ASCII.GetBytes(key);//创建用于hash的bytesbyte[] getbytes = new byte[n + keybytes.Length];for (int i = 0; i < n; i++){getbytes[i] = bytes[i];}keybytes.CopyTo(getbytes,n);System.Security.Cryptography.MD5 md5;md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create();return md5.ComputeHash(getbytes);}/// <summary>/// 获得从服务器返回的数字签名/// </summary>/// <param name="bytes"></param>/// <returns></returns>public static byte[] GetCurrentHash(byte[] bytes){byte[] hashbytes = null;if (bytes.Length < HASHSIZE) return hashbytes;hashbytes = new byte[HASHSIZE];for (int i = bytes.Length - HASHSIZE; i < bytes.Length; i++){hashbytes[i - (bytes.Length - HASHSIZE)] = bytes[i];}return hashbytes;}#region 比较两个bytes数组是否相等/// <summary>/// 比较两个bytes数组是否相等/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>public static bool ByteEquals(byte[] a,byte[] b){if (a == null || b == null || a.Length != b.Length) return false;for (int i = 0; i < a.Length; i++){if (a[i] != b[i]) return false;}return true;}#endregion#region 取字符串md5值/// <summary>/// md5值/// </summary>/// <param name="strToEncrypt">//数据: head1content1head2content2...m_secretKey</param>/// <returns></returns>public static string Md5Sum(string strToEncrypt){byte[] bs = UTF8Encoding.UTF8.GetBytes(strToEncrypt);System.Security.Cryptography.MD5 md5;md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create();byte[] hashBytes = md5.ComputeHash(bs);string hashString = "";for (int i = 0; i < hashBytes.Length; i++){hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2,'0');}return hashString.PadLeft(32,'0');}#endregion
}

PHP版本数据流

PHP版本的代码与C#版本如出一辙,只是换成了PHP的语法:

<?php 
//PHPStream.php
define("BYTE",1);
define("SHORT",2);
define("INT",4);
define("FLOAT",4);
define("HASHSIZE",16);
define("PKEY",123456);class PHPStream
{private $Key = "";public $bytes = "";public $Content = "";public $index = 0;public $ErrorRead = false;//开始写数据function  BeginWrite( $Key ){$this->index=0;$this->bytes="";$this->Content="";$this->ErrorRead=false;//total bytes length$this->WriteShort(0);//服务器这里在发送数据的时候会先去写入一个short,代表数据长度if ( strlen($Key) ){$this->Key=$Key;}}//写一个bytefunction WriteByte( $byte ){//$this->bytes.=pack('c',$byte);$this->bytes.=$byte;$this->index+=BYTE;}//写一个shortfunction WriteShort( $number ){$this->bytes.=pack("v",$number);$this->index+=SHORT;}//写一个32位intfunction WriteInt( $number ){$this->bytes.=pack("V",$number);$this->index+=INT;}//写一个floatfunction WriteFLOAT( $number ){$this->bytes.=pack("f",$number);$this->index+=FLOAT;}//写一个字符串function WriteString( $str ){$len=strlen($str);$this->WriteShort($len);$this->bytes.=$str;$this->index+=$len;}//写一组bytefunction WriteBytes( $bytes ){$len=strlen($bytes);$this->WriteShort($len);$this->bytes.=$bytes;$this->index+=$len;}function EndWrite(){//数字签名if ( strlen($this->Key)>0 ){$len=$this->index+HASHSIZE;$str=pack("v",$len);//猜测这里的bytes内部对应是0-1 2-3 4-5 6-7//猜测内部为键值对 $str[0] = $str[1]$this->bytes[0]=$str[0];//猜测为key值$this->bytes[1]=$str[1];//猜测为key值对应的value//获取md5值$hashbytes=md5($this->bytes.$this->Key,true);$this->bytes.=$hashbytes;}else {$str=pack("v",$this->index);$this->bytes[0]=$str[0];$this->bytes[1]=$str[1];}}//开始读入数据function BeginRead( $Key ){$this->index=0;$this->bytes="";$this->Content="";$this->ErrorRead=false;if ( strlen($Key)>0 )//strlen检测字符串长度{$this->Key=$Key;}}//读取POST信息function Read( $head ){if( isset($_POST[$head]) ){$this->Content.=$_POST[$head];return $_POST[$head];}else{$this->ErrorRead=true;}}//结束读取function EndRead(){if ($this->ErrorRead) return false;if (strlen($this->Key)<1) return true;//如果不需要签名验证则将原本的PKEY改为空字符串//取得数字签名$hashkey="";if ( isset($_POST["key"]) ) $hashkey=$_POST["key"];else {$this->ErrorRead=true;return false;}//重新计算数字签名$localhash=md5($this->Content.$this->Key);//比较数字签名if (strcmp($hashkey,$localhash)==0) return true;//strcmp检测两个字符串是否一致else{$this->ErrorRead=true;return false;}}
}
?>

三、数据传输测试

1.在Unity中创建一个C#脚本NetWorkManager.cs

在脚本中创建一个WWW实例,分别发送int、float、short和string类型的数据至服务器,服务器收到后再将这些数据返回给Unity,下面是C#代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class NetworkManager : MonoBehaviour {public const string URL = "http://192.168.1.5:8088/StreamTest.php";private void Start(){StartCoroutine(Test());}IEnumerator Test(){PostStream poststream = new PostStream();int integer = 1000;float number = 8.99f;short small = 30;string txt = "编程其乐无穷";//开始写入数据并指定需要签名认证poststream.BeginWrite(true);//写入数据Content: integer=1000poststream.Write("integer",integer.ToString());//写入数据Content: integer=1000&number=8.99poststream.Write("number",number.ToString());//写入数据Content: integer=1000&number=8.99&short=30poststream.Write("short",small.ToString());//写入数据Content: integer=1000&number=8.99&short=30&string=编程其乐无穷poststream.Write("string",txt);//1.最终签名认证的数据Content: integer=1000&number=8.99&short=30&string=编程其乐无穷&key=c344b95687a03452d4bf479a89affb94 //解释: c344b95687a03452d4bf479a89affb94为“10008.9930编程其乐无穷123456”字符串的MD5值  //123456为用于签名的密码 其组成是由写入的数组+密码组成//2.最终非签名认证的数据Content: integer=1000&number=8.99&short=30&string=编程其乐无穷poststream.EndWrite();//服务器Post请求WWW www = new WWW(URL,poststream.BYTES,poststream.Headers);yield return www;//无错误if (www.error != null){Debug.LogError(www.error);}else//读取返回值{poststream = new PostStream();poststream.BeginRead(www, true);poststream.ReadInt(ref integer);poststream.ReadFloat(ref number);poststream.ReadShort(ref small);poststream.ReadString(ref txt);bool ok = poststream.EndRead();if (ok){Debug.LogError(integer);Debug.LogError(number);Debug.LogError(small);Debug.LogError(txt);}else{Debug.LogError("error");}}}
}

2.服务器www目录创建StreamTest.php脚本代码如下:

<?php 
//StreamTest.php
header('Content-Type:text/html; charset=utf-8');
require_once("PHPStream.php");//引用PHPStream.php文件//read
$stream=new PHPStream();
$stream->BeginRead(PKEY);//与客户端对应的数字签名密码
$integer=$stream->Read("integer");//从传入的数据中找到Key值为integer的Value
$number=$stream->Read("number");//从传入的数据中找到Key值为number的Value
$short=$stream->Read("short");//从传入的数据中找到Key值为short的Value
$str=$stream->Read("string");//从传入的数据中找到Key值为string的Value
$ok=$stream->EndRead();if ($ok)
{//开始写入一个short: bytes=pack("v",0)//开始的index: index = 0+2$stream->BeginWrite(PKEY);//写入一个Int: bytes=pack("v",0)+pack("V",$integer)//当前index: index = 0 + 2 + 4$stream->WriteInt($integer);//写入一个Float: bytes=pack("v",0)+pack("V",$integer)+pack("f",$number)//当前index: index = 0 + 2 + 4 + 4$stream->WriteFloat($number);//写入一个Float: bytes=pack("v",0)+pack("V",$integer)+pack("f",$number)+pack("v",$short)//当前index: index = 0 + 2 + 4 + 4 + 2$stream->WriteShort($short);//写入一个String: bytes=pack("v",0)+pack("V",$integer)+pack("f",$number)+pack("v",$short)+[pack("v",strlen($str))+$str]//当前index: index = 0 + 2 + 4 + 4 + 2 + (2 + strlen($str))$stream->WriteString($str);//带有签名bytes 末尾加md5(bytes=pack("v",0)+pack("V",$integer)+pack("f",$number)+pack("v",$short)+[pack("v",strlen($str))+$str]) (无签名则不加)//带有签名index: index = 0 + 2 + 4 + 4 + 2 + (2 + strlen($str)) + 16 (无签名就去掉+16)$stream->EndWrite();echo $stream->bytes;
}
else
{echo "error";
}
?>

结果如下:

在这里插入图片描述

这里需要注意一个问题,自定义数据类写入过程和读取过程顺序必须一致,否则无法获取数据。

PHP中的pack与unpack的方法将数据转换为二进制的方法最好了解下。

相关文章:

C#与php自定义数据流传输

C#与php自定义数据流传输 介绍一、客户端与服务器数据传输流程图客户端发送数据给服务器&#xff1a;服务器返回数据给客户端&#xff1a; 二、自定义数据流C#版本数据流PHP版本数据流 三、数据传输测试1.在Unity中创建一个C#脚本NetWorkManager.cs2.服务器www目录创建StreamTe…...

redis和数据库的同步问题

今天突然想起来这个&#xff0c;就是那么突然&#xff0c;上次项目上用过redis&#xff0c;是一个消息已读未读的问题&#xff0c;由于消息挺多的&#xff0c;如果每次都去查数据库&#xff0c;那岂不是裂开&#xff0c;所以就存缓存了。 现在想想&#xff0c;还是不大行&#…...

Flink系列之:深入理解ttl和checkpoint,Flink SQL应用ttl案例

Flink系列之&#xff1a;深入理解ttl和checkpoint&#xff0c;Flink SQL应用ttl案例 一、深入理解Flink TTL二、Flink SQL设置TTL三、Flink设置TTL四、深入理解checkpoint五、Flink设置Checkpoint六、Flink SQL关联多张表七、Flink SQL使用TTL关联多表 一、深入理解Flink TTL …...

Wails中js调用go函数(1种go写法,2种js调用方法)

官方js调用go方法文档&#xff1a;https://wails.io/zh-Hans/docs/howdoesitwork a&#xff09;在app.go文件里写一个要js调用的go函数&#xff1a; func (a *App) JSCallGo(data1 string) string { return “test” } b&#xff09;运行 wails dev 命令&#xff0c…...

【我与java的成长记】之面向对象的初步认识

系列文章目录 能看懂文字就能明白系列 C语言笔记传送门 &#x1f31f; 个人主页&#xff1a;古德猫宁- &#x1f308; 信念如阳光&#xff0c;照亮前行的每一步 文章目录 系列文章目录&#x1f308; *信念如阳光&#xff0c;照亮前行的每一步* 前言一、什么是面向对象面向过程…...

面试题之二HTTP和RPC的区别?

面试题之二 HTTP和RPC的区别&#xff1f; Ask范围&#xff1a;分布式和微服务 难度指数&#xff1a;4星 考察频率&#xff1a;70-80% 开发年限&#xff1a;3年左右 从三个方面来回答该问题&#xff1a; 一.功能特性 1)HTTP是属于应用层的协议&#xff1a;超文本传输协议…...

初试Kafka

Kafka 是一个分布式流处理平台&#xff0c;通常用作消息中间件&#xff0c;它可以处理大规模的实时数据流。以下是从零开始使用 Kafka 作为消息中间件的基本教程&#xff1a; 步骤 1: 下载和安装 Kafka 访问 Apache Kafka 官方网站&#xff1a;Apache Kafka下载最新的 Kafka …...

SuperMap Hi-Fi 3D SDK for Unity基础开发教程

作者&#xff1a;kele 一、背景 众所周知&#xff0c;游戏引擎&#xff08;Unity&#xff09;功能强大&#xff0c;可以做出很多炫酷的游戏和动画效果&#xff0c;这部分功能的实现往往不仅仅是靠可视化界面就能够实现的&#xff0c;还需要代码开发。SuperMap Hi-Fi SDKS for …...

Upload-lab(pass1~2)

Pass-1-js检查 这里检验 因为是前端js校验,所以只用绕过js前端校验 用burp抓包修改文件类型 写一个简易版本的php Pass-2-只验证Content-type 仅仅判断content-type类型 因此上传shell.php抓包修改content-type为图片类型&#xff1a;image/jpeg、image/png、image/gif...

Linux:查询当前进程或线程的资源使用情况

目录 一、/proc/[PID]/下的各个文件1、proc简介2、/proc/[PID]/详解 二、通过Linux API获取当前进程或线程的资源使用情况1、getrusage2、sysinfo3、times 在工作中&#xff0c;我们排除app出现的一些性能/资源问题时&#xff0c;通常要先知道当前app的资源使用情况&#xff0c…...

unityc用vs2017介绍

21版unity能用17vs&#xff0c;只要在unity的Edit/Preferences/ExternalTools里面改既可。...

单元测试实战

文章目录 为什么要做单元测试&#xff1f;单元测试的几个核心要点是&#xff1a;单元测试目标单元测试框架JUnitTestNG 单元测试工具&#xff1a; 为什么要做单元测试&#xff1f; 测试代码&#xff1a;通过编写和运行单元测试&#xff0c;开发者能够快速验证代码的各个部分是否…...

WebService

调试工具&#xff1a;Postman、SoapUI Soap WebService :.net WCF 、Java CFX WebService三要素&#xff1a; SOAP&#xff08;Simple Object Access Protocol&#xff09;&#xff1a;用来描述传递信息的格式&#xff0c; 可以和现存的许多因特网协议和格式结合使用&#x…...

Nestjs使用log4j打印日志

众所周知&#xff0c;nest是自带日志的。但是好像没有log4j香&#xff0c;所以咱们来用log4j吧~ 我只演示最简单的用法&#xff0c;用具体怎么样用大家可以自己进行封装。就像前端封装自己的请求一样。 一、安装 yarn add log4js stacktrace-js 二、使用 主要就三个文件&a…...

Selenium - 自动化测试框架

Selenium 介绍 Selenium 是目前用的最广泛的 Web UI 自动化测试框架&#xff0c;核心功能就是可以在多个浏览器上进行自动化测试&#xff0c;支持多种编程语言&#xff0c;目前已经被 google&#xff0c;百度&#xff0c;腾讯等公司广泛使用。 开发步骤 1、配置 google 驱动…...

RFID技术在汽车制造:提高生产效率、优化物流管理和增强安全性

RFID技术在汽车制造:提高生产效率、优化物流管理和增强安全性 随着科技的进步&#xff0c;物联网技术已经深入到各个领域&#xff0c;尤其在制造业中&#xff0c;RFID技术以其独特的优势&#xff0c;如高精度追踪、实时数据收集和自动化操作&#xff0c;正在改变传统的生产方式…...

git异常

1.异常现象 换机新安装 Git 后&#xff0c;拉代码时出现问题&#xff1a; Unable to negotiate with 10.18.18.18 port 29418: no matching key exchange method found. Their offer: diffie-hellman-group14-sha1,diffie-hellman-group1-sha1 fatal: Could not read from rem…...

【C语言学习疑难杂症】第12期:如何从汇编角度深入理解y = (*--p)++这行代码(易懂版)

对于如下代码,思考一下输出结果是什么? int a[] = {5, 8, 7, 6, 2, 7, 3}; int y, *p = &a[1]; y = (*--p)++; printf("%d ",y); printf("%d",a[0]); 这个代码看似简单,但是在“y = (*--p)++;”这行代码里,编译器做了很多工作。 我们在vs2022的…...

5G阅信应用场景有哪些?

5G阅信的应用场景非常广泛&#xff0c;以下是一些常见的应用场景&#xff1a; 1.工业自动化&#xff1a;5G阅信可以连接各种工业设备和传感器&#xff0c;实现设备之间的实时通信和控制&#xff0c;提高生产效率和自动化水平。 2.物联网和智能家居&#xff1a;5G阅信可以连接各…...

使用OpenSSL生成自签名SSL/TLS证书和私钥

使用OpenSSL生成自签名SSL/TLS证书和私钥 前提&#xff1a; 系统安装了OpenSSL&#xff1b; 系统&#xff1a;windows、linux都可&#xff1b; 1 生成私钥 创建一个名为 server.key 的私钥文件&#xff0c;并使用 RSA 算法生成一个 2048 位的密钥。 openssl genrsa -out s…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...