当前位置: 首页 > 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…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

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

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