Unity自定义数据流
来源:互联网 发布:普奇神父知乎 编辑:程序博客网 时间:2024/05/21 08:49
客户端需要添加脚本PostStream.cs
using UnityEngine;using System.Collections.Generic;using System.Text;public class PostStream{ // 保存域头 public System.Collections.Hashtable Headers = new System.Collections.Hashtable(); // 末尾16个字节保存md5数字签名 const int HASHSIZE = 16; // byte占一个字节 const int BYTE_LEN = 1; // short 占2个字节 const int SHORT16_LEN = 2; // int 占4个字节 const int INT32_LEN = 4; // int 占4个字节 const int FLOAT_LEN = 4; private int m_index = 0; public int Length { get { return m_index; } } // 秘密密码,用于数字签名 private string m_secretKey = "123456"; // 存储Post信息 private string[,] m_field; private const int MAX_POST = 128; private const int PAIR = 2; private const int HEAD = 0; private const int CONTENT = 1; // 收到的字节数组 private byte[] m_bytes = null; public byte[] BYTES { get { return m_bytes; } } // 发送的字符串 private string m_content = ""; // 读取是否出现错误 private bool m_errorRead = false; // 是否进行数字签名 private bool m_sum = true; public PostStream() { Headers = new System.Collections.Hashtable(); m_index = 0; m_bytes = null; m_content = ""; m_errorRead = false; } 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"); } 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); } else { m_content += ("&" + head + "=" + content); } } public void EndWrite() { if (m_sum) { string hasstring = ""; for (int i = 0; i < MAX_POST; i++) { hasstring += m_field[i, CONTENT]; } hasstring += m_secretKey; m_content += "&key=" + Md5Sum(hasstring); } m_bytes = UTF8Encoding.UTF8.GetBytes(m_content); } // ****************************************************************************************************** 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 lenght = 0; this.ReadShort(ref lenght); if (lenght != m_bytes.Length) { m_index = lenght; 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; } // 忽略一个字节 public void IgnoreByte() { if (m_errorRead) return; m_index += BYTE_LEN; } // 读取一个字节 public void ReadByte(ref byte bts) { if (m_errorRead) return; bts = m_bytes[m_index]; m_index += BYTE_LEN; } // 读取一个short public void ReadShort(ref short number) { if (m_errorRead) return; number = System.BitConverter.ToInt16(m_bytes, m_index); m_index += SHORT16_LEN; } // 读取一个int public void ReadInt(ref int number) { if (m_errorRead) return; number = System.BitConverter.ToInt32(m_bytes, m_index); m_index += INT32_LEN; } // 读取一个float public void ReadFloat(ref float number) { if (m_errorRead) return; number = System.BitConverter.ToSingle(m_bytes, m_index); m_index += FLOAT_LEN; } // 读取一个字符串 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; } // 读取一个bytes数组 public void ReadBytes(ref byte[] byts) { if (m_errorRead) return; short len=0; ReadShort(ref len); // 字节流 byts = new byte[len]; for (int i = m_index; i < m_index + len; i++) { byts[i - m_index] = m_bytes[i]; } m_index += len; } // 结束读取 public bool EndRead() { if (m_errorRead) return false; else return true; } // 重新计算本地数字签名 public static byte[] GetLocalHash(byte[] bytes, string key) { // hash bytes byte[] hashbytes = null; int n = bytes.Length-HASHSIZE; if ( n<0 ) return hashbytes; // 获得key的bytes byte[] keybytes = System.Text.ASCIIEncoding.ASCII.GetBytes(key); // 创建用于hash的bytes byte[] 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 = System.Security.Cryptography.MD5CryptoServiceProvider.Create(); return md5.ComputeHash(getbytes); } // 获得当前数字签名 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; } // 比较两个bytes数组是否相等 public static bool ByteEquals(byte[] a, byte[] b) { if (a == null || b == null) { return false; } if (a.Length != b.Length) return false; for (int i = 0; i < a.Length; i++) { if (a[i] != b[i]) { return false; } } return true; } // 数字签名 public static string Md5Sum(string strToEncrypt) { byte[] bs = UTF8Encoding.UTF8.GetBytes(strToEncrypt); System.Security.Cryptography.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'); }}
服务端需要添加PHPStream.php脚本
<?phpdefine("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;// ---------------------------------------------// write stream// ---------------------------------------------function BeginWrite( $key ){$this->index=0;$this->bytes="";$this->Content="";$this->ErrorRead=false;//total bytes length$this->WriteShort(0);if ( strlen($key)>0 ){$this->Key=$key;}}function WriteByte( $byte ){//$this->bytes.=pack('c',$byte);$this->bytes.=$byte;$this->index+=BYTE;}function WriteShort( $number ){$this->bytes.=pack("v",$number);$this->index+=SHORT;}function WriteInt( $number ){$this->bytes.=pack("V",$number);$this->index+=INT;}function 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;}function WriteBytes( $bytes ){$len=strlen($bytes);$this->WriteShort($len);$this->bytes.=$bytes;$this->index+=$len;}function EndWrite(){// sumif (strlen($this->Key)>0){$len=$this->index+HASHSIZE;$str=pack("v",$len);$this->bytes[0]=$str[0];$this->bytes[1]=$str[1];$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];}}// ************************************************************************************// ---------------------------------------------// read stream// ---------------------------------------------function BeginRead( $key ){$this->index=0;$this->bytes="";$this->Content="";$this->ErrorRead=false;if ( strlen($key)>0 ){$this->Key=$key;}}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 not use a keyif (strlen($this->Key)<1)return true;// record hashkey$hashkey="";if ( isset($_POST["key"]) ){$hashkey=$_POST["key"];}else{$this->ErrorRead=true;return false;}// hash it again$localhash=md5($this->Content.$this->Key);// if okif (strcmp($hashkey,$localhash)==0){return true;}else{$this->ErrorRead=true;return false;}}}?>
接下来测试客户端自定义一个数据流(由int float short 和 string四种类型)传给服务器,服务器原样返回,再由客户端解析输出在控制台
客户端关键代码
OnGUI()中添加如下按钮
if (GUI.Button(new Rect(10, 400, 150, 30), "自定义数据流")) { StartCoroutine(sendUserDisignData()); }
添加sendUserDisignData()函数
IEnumerator sendUserDisignData() { //自定义数据流写入数据 PostStream postStream = new PostStream(); int integer = 1000; float number = 8.99f; short small = 30; string txt = "测试自定义数据流"; postStream.BeginWrite(true); postStream.Write("integer", integer.ToString()); postStream.Write("number", number.ToString()); postStream.Write("short", small.ToString()); postStream.Write("string", txt); postStream.EndWrite(); // WWW www = new WWW("http://127.0.0.1/TestPHP/StreamTest.php", postStream.BYTES, postStream.Headers); yield return www; if (www.error != null) { m_info = www.error; yield return null; } 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 isReadOk = postStream.EndRead(); if (isReadOk) { Debug.Log(integer); Debug.Log( number); Debug.Log( small); Debug.Log( txt); } } }
在服务器的TestPHP路径下添加服务器测试StreamTest.php脚本
<?phpheader('Content-Type:text/html; charset=utf-8' );require_once("PHPStream.php");// read$stream=new PHPStream();$stream->BeginRead(PKEY);$integer=$stream->Read("integer");$number=$stream->Read("number");$short=$stream->Read("short");$str=$stream->Read("string");$ok=$stream->EndRead();if ($ok){$stream->BeginWrite(PKEY);$stream->WriteInt($integer);$stream->WriteFloat($number);$stream->WriteShort($short);$stream->WriteString($str);$stream->EndWrite();echo $stream->bytes;}else{echo "error";}?>
运行Unity可以在控制台看到相应的数据输出
0 0
- Unity自定义数据流
- Unity UGUI 折线图 支持数据流
- 【Unity】Unity自定义热键代码
- pig自定义FilterFunc实现数据流的过滤
- RxJava 驯服数据流之自定义操作函数
- RxJava 驯服数据流之自定义操作函数
- 数据流
- 数据流
- 数据流
- 数据流
- 数据流
- 数据流
- Unity 自定义菜单栏
- [Unity实战]自定义mesh
- Unity自定义定时器
- Unity自定义菜单栏
- Unity 自定义事件
- Unity中的自定义鼠标
- mySQL中replace的用法
- 2012年5月SAT香港真题解析
- jni 简介
- 语法错误 : 缺少“;”(在“<”的前面)
- android的activitygroup使用
- Unity自定义数据流
- 转载 httpclient 上传、下载文件
- Android的LinearLayout.getLayoutParams().width 和 LinearLayout.getWidth() 的区别
- 静态方法的线程安全
- HDU-5280
- 详解 Too many open files
- 线程池与ThreadPoolExecutor学习笔记
- shell环境变量以及set,env,export的区别
- Mommy, I found it!, 15 Awesome Linux Find Command Examples