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