记录下之前开发SLG时,处理的网络通信相关的逻辑
ByteArray类
using UnityEngine; using System; namespace IO { public class ByteArray { protected byte[] m_buffer = null; protected int readOffset = 0; protected int writeOffset = 0; public int GetDataLength() { return writeOffset - readOffset; } public int GetHeadOffset() { return readOffset; } public void SetHeadOffset(int offset) { readOffset = offset; } public byte[] readBytes(int nLen) { if (readOffset + nLen > this.m_buffer.Length) { Debug.Log(" Failed: 长度越界 NetReader: getBYTE "); throw new IndexOutOfRangeException(" Failed: 长度越界 NetReader: getBYTE "); } byte[] buf = new byte[nLen]; Buffer.BlockCopy(m_buffer, readOffset, buf, 0, nLen); this.readOffset += nLen; return buf; } public int INCREAT_SIZE = 100; void cleanReadOffset() { Buffer.BlockCopy(m_buffer,readOffset,m_buffer,0,writeOffset - readOffset); readOffset = 0; writeOffset -= readOffset; } void requestBufferSize(int expectLength) { if (m_buffer == null) { m_buffer = new byte[0]; readOffset = 0; writeOffset = 0; } int remainSize = m_buffer.Length - writeOffset; if (remainSize < expectLength) { if(remainSize + readOffset >= expectLength) { cleanReadOffset(); return; } int newSize = Mathf.CeilToInt((expectLength + GetDataLength()) / (float)INCREAT_SIZE) * INCREAT_SIZE; byte[] buf = new byte[newSize]; Buffer.BlockCopy(m_buffer,readOffset, buf, 0,writeOffset - readOffset); m_buffer = buf; readOffset = 0; writeOffset -= readOffset; } } public void writeBytes(byte[] buffer) { if (buffer.Length < 1) { return; } requestBufferSize(buffer.Length); Buffer.BlockCopy(buffer, 0, m_buffer, writeOffset, buffer.Length); writeOffset += buffer.Length; } public int dataSize() { if (m_buffer == null) { return 0; } return m_buffer.Length - readOffset; } public int dataPtr() { return readOffset; } public string dataString() { return ""; } public void consumeByte(int len) { System.Diagnostics.Debug.Assert(m_buffer.Length >= readOffset + len); readOffset += len; } public void clearBuffer() { m_buffer = new byte[0]; readOffset = 0; } sbyte byteAtIndex(int index) { if (index > m_buffer.Length) { return 0; } return Convert.ToSByte(m_buffer[index]); } public sbyte readSbyte() { int nLen = sizeof(byte); if (this.readOffset + nLen > this.m_buffer.Length) { Debug.Log(" Failed: 长度越界 NetReader: readInt8 "); throw new IndexOutOfRangeException(" Failed: 长度越界 NetReader: readInt8 "); } byte bt = m_buffer[readOffset]; this.readOffset += nLen; sbyte sb; unchecked { sb = (sbyte)bt; } return sb; } public byte readInt8() { int nLen = sizeof(byte); if (this.readOffset + nLen > this.m_buffer.Length) { Debug.Log(" Failed: 长度越界 NetReader: readInt8 "); throw new IndexOutOfRangeException(" Failed: 长度越界 NetReader: readInt8 "); } byte bt = m_buffer[readOffset]; this.readOffset += nLen; return bt; } public short readInt16() { int nLen = sizeof(short); if (this.readOffset + nLen > this.m_buffer.Length) { Debug.Log(" Failed: 长度越界 NetReader: readInt16 "); throw new IndexOutOfRangeException(" Failed: 长度越界 NetReader: readInt16 "); } short val = BitConverter.ToInt16(m_buffer, readOffset); readOffset += nLen; return val; } public int readInt32() { int nLen = sizeof(int); if (this.readOffset + nLen > this.m_buffer.Length) { Debug.Log(" Failed: 长度越界 NetReader: readInt32 "); throw new IndexOutOfRangeException(" Failed: 长度越界 NetReader: readInt32 "); } int val = BitConverter.ToInt32(m_buffer, readOffset); readOffset += nLen; return val; } public long readInt64() { int nLen = sizeof(Int64); if (this.readOffset + nLen > this.m_buffer.Length) { Debug.Log(" Failed: 长度越界 NetReader: readInt64 "); throw new IndexOutOfRangeException(" Failed: 长度越界 NetReader: readInt64 "); } long val = BitConverter.ToInt64(m_buffer, readOffset); readOffset += nLen; return val; } public void writeInt8(byte value) { byte[] val = new byte[1]; val[0] = value; writeBytes(val); } public void writeInt16(short value) { byte[] val = BitConverter.GetBytes(value); writeBytes(val); } public void writeInt32(int value) { byte[] val = BitConverter.GetBytes(value); writeBytes(val); } public void writeInt64(long value) { byte[] val = BitConverter.GetBytes(value); writeBytes(val); } public void writeByteBuffer(ByteArray buffer) { writeBytes(buffer.m_buffer); } public ByteArray copyBufferPart(int startIndex, int nCount) { ByteArray buffer = new ByteArray(); byte[] ByteArray = new byte[nCount]; Buffer.BlockCopy(m_buffer, startIndex, ByteArray, 0, nCount); buffer.writeBytes(ByteArray); return buffer; } public ByteArray copyBufferAll() { ByteArray buffer = new ByteArray(); int byteLen = dataSize() - dataPtr(); byte[] ByteArray = new byte[byteLen]; Buffer.BlockCopy(m_buffer, readOffset, ByteArray, 0, byteLen); buffer.writeBytes(ByteArray); return buffer; } //void cleanHeadOffset(); public byte[] getBuffer() { if (m_buffer !=null) { return m_buffer; } return new byte[0]; } } }
ByteArrayQueue类
using System; using System.Collections; namespace IO { public class ByteArrayQueue { protected ArrayList m_queue; public ByteArrayQueue() { m_queue = new ArrayList(); } public void pushBack(ByteArray buffer) { m_queue.Add(buffer); } public void pushFront(ByteArray buffer) { m_queue.Insert(0, buffer); } public void popBack() { m_queue.RemoveAt(m_queue.Count); } public void popFront() { m_queue.RemoveAt(0); } //public void popBackAndDelete(); //public void popFrontAndDelete(); public void removeAll() { m_queue.Clear(); } public void deleteAll() { m_queue.Clear(); } public ByteArray front() { return (ByteArray)m_queue[0]; } public ByteArray back() { return (ByteArray)m_queue[m_queue.Count]; } public ByteArray frontAndPop() { if (m_queue.Count < 1) { return null; } ByteArray buf = (ByteArray)m_queue[0]; m_queue.RemoveAt(0); return buf; } public ByteArray backAndPop() { if (m_queue.Count < 1) { return null; } ByteArray buf = (ByteArray)m_queue[m_queue.Count]; m_queue.RemoveAt(m_queue.Count); return buf; } //public void lockQueue(); //public void unlockQueue(); public bool empty() { return m_queue.Count == 0; } public int Count() { return m_queue.Count; } } }
ByteStream类
using System; using System.Collections; namespace IO { public class ByteStream { protected ByteArray m_pBuffer; public byte readInt8() { return m_pBuffer.readInt8(); } public void writeInt8(byte value) { m_pBuffer.writeInt8(value); } public Int16 readInt16() { return m_pBuffer.readInt16(); } public void writeInt16(short value) { m_pBuffer.writeInt16(value); } public Int32 readInt32() { return m_pBuffer.readInt32(); } public void writeInt32(int value) { m_pBuffer.writeInt32(value); } public Int64 readInt64() { return m_pBuffer.readInt64(); } public void writeInt64(Int64 value) { m_pBuffer.writeInt64(value); } public string readString() { Int16 nStrLen = 0; nStrLen = readInt16(); System.Diagnostics.Debug.Assert(m_pBuffer.dataSize() >= nStrLen); byte[] b = m_pBuffer.readBytes(nStrLen); string s = System.Text.Encoding.UTF8.GetString(b); return s; } public void writeString(string s) { short len = (short)s.Length; writeInt16(len); byte[] val = System.Text.Encoding.UTF8.GetBytes(s); m_pBuffer.writeBytes(val); } public ByteArray byteBuffer() { return m_pBuffer; } public void attachBuffer(ByteArray pBuffer) { if (m_pBuffer != null) { detachBuffer(); } m_pBuffer = pBuffer; } public void detachBuffer() { m_pBuffer = null; } } }
Endian类
using System; namespace IO { //大小端转换 public static class Endian { public static short SwapInt16(this short n) { return (short)(((n & 0xff) << 8) | ((n >> 8) & 0xff)); } public static ushort SwapUInt16(this ushort n) { return (ushort)(((n & 0xff) << 8) | ((n >> 8) & 0xff)); } public static int SwapInt32(this int n) { return (int)(((SwapInt16((short)n) & 0xffff) << 0x10) | (SwapInt16((short)(n >> 0x10)) & 0xffff)); } public static uint SwapUInt32(this uint n) { return (uint)(((SwapUInt16((ushort)n) & 0xffff) << 0x10) | (SwapUInt16((ushort)(n >> 0x10)) & 0xffff)); } public static long SwapInt64(this long n) { return (long)(((SwapInt32((int)n) & 0xffffffffL) << 0x20) | (SwapInt32((int)(n >> 0x20)) & 0xffffffffL)); } public static ulong SwapUInt64(this ulong n) { return (ulong)(((SwapUInt32((uint)n) & 0xffffffffL) << 0x20) | (SwapUInt32((uint)(n >> 0x20)) & 0xffffffffL)); } } }
Net类
using System; using System.Collections.Generic; using System.Net.Sockets; using System.Threading; using UnityEngine; using IO; using UnityEditor; enum KickCode { /** 0 - 重复登录 */ eDUPLICATE_LOGIN = 0, /** 1 - 玩家被封禁 */ eBLOCK_LOGIN, /** 2 - 登录超时 */ eLOGIN_TIMEOUT, }; enum NetErrorType { eSendError = 0, /*发送数据错误 -(重激活)*/ eRecvError = 1, /*接受数据错误 -(重激活)*/ }; enum NetStatue { /** 0 - 未连接 */ eDISCONNECT = 0, /** 1 - 正常工作中 */ eWORKING, /** 2 - 事务行错误 */ eTRANSERROR, }; namespace NetCore { public class Net : MonoBehaviour { AutoResetEvent threadExitEvent = new AutoResetEvent(false); bool threadExit = true; /*套接字*/ private Socket _socket = null; /*异步线程*/ private Thread _thread = null; /**/ private const int TimeOut = 30;//30秒的超时时间 /*端口*/ private int _port; /*IP*/ private string _ip; public bool stopReceive = false; public bool stopSend = false; public bool sendFailed = false; private Mutex flagWorkingMutex = new Mutex(); private bool bWorking = false; private LinkedList<Action> threadTaskQueue = new LinkedList<Action>(); private LinkedList<Action> taskQueue = new LinkedList<Action>(); /*发送队列*/ private ByteArrayQueue _sendQueue; /*接受队列*/ private ByteArrayQueue _receiveQueue; //错误队列 private List<int> _errorQueue; //最大尝试次数 private int mostRetryTimes = 3; Action<int> fnErrorNotify = null; //网络状态 private NetStatue statue = NetStatue.eDISCONNECT; /// 检测移动设备的网络环境 public bool CheckInternetReachable() { /*该状态只能检测WIFI和运营商网络,热点可能无法被检测到*/ UnityEngine.NetworkReachability state = UnityEngine.Application.internetReachability; if (state == NetworkReachability.NotReachable) return false; return true; } /// 获取网络状态类型 /// <returns>0 网络未连接 1 运营商网络 2 Wifi </returns> public int GetDeviceInterntState() { UnityEngine.NetworkReachability state = UnityEngine.Application.internetReachability; return (int)state; } public void Awake() { _sendQueue = new ByteArrayQueue(); _receiveQueue = new ByteArrayQueue(); _errorQueue = new List<int>(); //StartNet(); } // void OnGUI() // { // if (GUI.Button(new Rect(1000, 0, 200, 50), "断线")) // { // _pushTask(() => // { // closeConnect(); // // onNetRecvError(); // }); // } // // // } private void _pushThreadTask(Action fn) { lock (threadTaskQueue) { threadTaskQueue.AddFirst(fn); } } private void _pushTask(Action fn) { lock (taskQueue) { taskQueue.AddFirst(fn); } } private void _handleThreadTask() { lock (threadTaskQueue) { while (threadTaskQueue.Count > 0) { Action act = threadTaskQueue.First.Value; threadTaskQueue.RemoveFirst(); act(); } } } private void _handeTask() { lock (taskQueue) { while (taskQueue.Count > 0) { Action act = taskQueue.First.Value; taskQueue.RemoveFirst(); act(); } } } public void Update() { _handeTask(); } /// 设置IP和端口 public void SetIp(string ip, int port) { _ip = ip; _port = port; } /// 初始化网络 public void startNet() { Debug.Assert(_socket == null); Debug.Assert(_thread == null); if (_socket != null || _thread != null) return; stopReceive = false; stopSend = false; _thread = new Thread(new ThreadStart(_threadEntry)); _thread.Start(); return; } /// <summary> /// 网络正在连接中 /// </summary> /// <returns></returns> public bool isConnected() { if (_socket == null) return false; return _socket.Connected; } public bool isWorking() { return bWorking; } public void offWorking() { lock (flagWorkingMutex) { bWorking = false; } } public void working() { lock (flagWorkingMutex) { bWorking = true; } } public void ClearPacketQueue() { lock (_sendQueue) { _sendQueue.removeAll(); } } public void connectNetAsyc(Action<bool> cb) { if (_socket!=null) return; _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ClearPacketQueue(); lock (threadTaskQueue) { _pushThreadTask(() => { IAsyncResult rst = null; try { rst = _socket.BeginConnect(_ip, _port, null, null); rst.AsyncWaitHandle.WaitOne(2000, true); } catch (Exception ex) { Debug.Log(ex.ToString()); _pushTask(() => { cb(false); }); } bool success = false; if (rst.IsCompleted && _socket.Connected) { success = true; _socket.EndConnect(rst); Debug.Log("网络连接成功"); } else { success = false; _closeSocket(); Debug.Log("网络连接失败"); } if (cb != null) _pushTask(() => { cb(success); }); }); } } /// <summary> /// 压入发送数据 /// </summary> /// <param name="buffer"></param> public void sendBytes(ByteArray buffer) { if (sendFailed) { sendFailed = false; _pushTask(() => { closeConnect(); onNetSendError(); }); return; } lock (_sendQueue) { _sendQueue.pushBack(buffer); } } /// <summary> /// 获取第一条接受的数据 /// </summary> public ByteArray pickRevQueue() { ByteArray byteBuffer = null; lock (_receiveQueue) { byteBuffer = _receiveQueue.frontAndPop(); } return byteBuffer; } //拾取错误 public int pickErrorQueue() { int error = -1; lock (_errorQueue) { if (_errorQueue.Count > 0) { error = _errorQueue[0]; _errorQueue.RemoveAt(0); } } return error; } public void clearDataQueue() { _sendQueue.removeAll(); _receiveQueue.removeAll(); } private void _closeSocket() { if (_socket == null) return; _socket.Close(); _socket = null; offWorking(); } /// <summary> /// 断开链接 /// </summary> public void closeConnect() { if (!isConnected()) return; _pushThreadTask(() => { _closeSocket(); threadExitEvent.Set(); }); threadExitEvent.WaitOne(); } public void shutdownThread() { if (_thread == null) return; _pushThreadTask(() => { threadExit = false; }); _thread.Join(); _thread = null; } /// <summary> /// 断开链接 /// </summary> public void shutdownNet() { if (_thread == null) return; closeConnect(); shutdownThread(); clearDataQueue(); } /// <summary> /// 线程 /// </summary> private void _threadEntry() { while (threadExit) { if (_socket != null) { _sendData(); _recvData(); } _handleThreadTask(); Thread.Sleep(50); } threadExit = true; } /// <summary> /// 发送数据 /// </summary> private bool _sendData() { if (!isConnected() || !isWorking() || stopSend) return false; ByteArray buffer; lock (_sendQueue) { if (_sendQueue.empty()) return false; buffer = _sendQueue.front(); } byte[] data = buffer.getBuffer(); try { int len = buffer.GetDataLength(); if (len < 8) { Debug.Log("发送数据长度小于8"); } IAsyncResult asyncSend = _socket.BeginSend(data, 0, buffer.GetDataLength(), SocketFlags.None, null, null); bool bSuccess = asyncSend.AsyncWaitHandle.WaitOne(5000, true); if (!bSuccess) { Debug.Log("发送数据失败"); _closeSocket(); _pushTask(() => { onNetSendError(); }); } else { lock (_sendQueue) { _sendQueue.popFront(); } } return true; } catch (Exception ex) { Debug.Log("发送数据失败,请检查网络连接 :" + ex.ToString()); _closeSocket(); offWorking(); _pushTask(() => { onNetSendError(); }); } return false; } private void _recvError() { _closeSocket(); _pushTask(() => { onNetRecvError(); }); offWorking(); } /// <summary> /// 异步接受数据 /// </summary> private void _recvData() { if (!isConnected() || !isWorking() || stopReceive) return; try { if (_socket.Poll(5, SelectMode.SelectRead)) { byte[] prefix = new byte[4]; //包长度 int recnum = 0; recnum = _socket.Receive(prefix); if (recnum == 4) { int len = BitConverter.ToInt32(prefix, 0); int datalen = Endian.SwapInt32(len) - 4; byte[] data = new byte[datalen]; int startIndex = 0; recnum = 0; do { int rev = _socket.Receive(data, startIndex, datalen - recnum, SocketFlags.None); recnum += rev; startIndex += rev; } while (recnum != datalen); ByteArray buffer = new ByteArray(); buffer.writeBytes(data); lock (_receiveQueue) { _receiveQueue.pushBack(buffer); } } else if (recnum == 0) { Debug.Log("网络接收到0字节(断开)."); _recvError(); } } else if (_socket.Poll(5, SelectMode.SelectError)) { Debug.Log("SelectError Socket 状态错误"); _recvError(); } } catch (Exception ex) { Debug.Log("接收网络数据异常:" + ex.ToString()); _recvError(); } } /// <summary> /// 接受队列是否为空 /// </summary> public bool isRecvQueueEmpty() { bool rst = false; rst = _receiveQueue.empty(); return rst; } private void onNetRecvError() { notifyError(NetErrorType.eRecvError); } private void onNetSendError() { notifyError(NetErrorType.eSendError); } private void notifyError(NetErrorType err) { if (fnErrorNotify != null) { fnErrorNotify((int)err); } } public void setErrorNotify(Action<int> lfn) { fnErrorNotify = lfn; } } }
PackProtocol类
using System; using System.Collections.Generic; using IO; namespace NetCore { public class PackProtocol { public short m_sn = 0; public ByteArray signByteStream(byte module, byte method, byte[] data) { //* <p>[4字节] 长度 //* <p>[1字节] 校验码 //* <p>[1字节] 循环顺序号(从0开始,每次请求+1,不符合则断开; 0,1,2,...,127,-128,-127,...,-1,0,1,...) //* <p>[1字节] 模块号 //* <p>[1字节] 命令号 //包头长度 8 字节 int len = data.Length + 8; short validateCode = fnvhash(m_sn, module, method, len); ByteArray byteBuffer = new ByteArray(); byteBuffer.writeInt32(Endian.SwapInt32(len)); byteBuffer.writeInt8((byte)validateCode); byteBuffer.writeInt8((byte)m_sn); byteBuffer.writeInt8(module); byteBuffer.writeInt8(method); byteBuffer.writeBytes(data); m_sn++; return byteBuffer; } public ByteArray signByteStream(ByteArray byteBuffer) { //* <p>[4字节] 长度 //* <p>[1字节] 校验码 //* <p>[1字节] 循环顺序号(从0开始,每次请求+1,不符合则断开; 0,1,2,...,127,-128,-127,...,-1,0,1,...) //* <p>[1字节] 模块号 //* <p>[1字节] 命令号 //包头长度 8 字节 //self.netSendPackVStream:writeInt8(packet.req[‘_MOD_‘]) //self.netSendPackVStream:writeInt8(packet.req[‘_MED_‘]) //self.netSendPackVStream:writeInt32(0)--预留六字节 //self.netSendPackVStream:writeInt16(0) //byte[] data = byteBuffer.getBuffer(); int len = byteBuffer.GetDataLength(); byte module = byteBuffer.readInt8(); byte method = byteBuffer.readInt8(); short validateCode = fnvhash(m_sn, module, method, len); ByteArray buf = new ByteArray(); buf.writeInt32(Endian.SwapInt32(len)); buf.writeInt8((byte)validateCode); buf.writeInt8((byte)m_sn); buf.writeInt8(module); buf.writeInt8(method); byte[] src = buf.getBuffer(); byte[] dec = byteBuffer.getBuffer(); Buffer.BlockCopy(src, 0, dec, 0, buf.GetDataLength()); byteBuffer.SetHeadOffset(0); m_sn++; return buf; } public void resetSN() { m_sn = 0; } private short fnvhash(short sn, short module, short cmd, Int32 len) { int hash = 117; int prime = 101; int lenLow = len & 0xFFFF; int lenHight = (int)(len & 0xFFFF0000) >> 16; hash = (hash ^ sn) * prime; hash = (hash ^ module) * prime; hash = (hash ^ cmd) * prime; hash = (hash ^ lenLow) * prime; hash = (hash ^ lenHight) * prime; return (short)(hash & 0xFF); } } }
VarintStream类
using System; using System.Collections; namespace IO { public class VarintStream : ByteStream { public sbyte readVarint8() { return (sbyte)readVarint32ByteToSbyte(); } public void writeVarint8(byte value) { writeVarint32Byte(value); } public Int16 readVarint16() { return (Int16)readVarint32Byte(); } public void writeVarint16(Int16 value) { writeVarint32Byte((UInt16)value); } public Int32 readVarint32() { return (Int32)readVarint32Byte(); } public void writeVarint32(Int32 value) { writeVarint32Byte((UInt32)value); } public Int64 readVarint64() { return (Int64)readVarint64Byte(); } public void writeVarint64(Int64 value) { writeVarint64Byte((UInt64)value); } protected void writeVarint32Byte(UInt32 value) { if (value < 128) { writeInt8((byte)value); return; } while (value > 127) { writeInt8((byte)((value & 0x7F) | 0x80)); value >>= 7; } writeInt8((byte)value); } protected uint readVarint32Byte() { int tmp = m_pBuffer.readInt8(); if (tmp < 128) { return (uint)tmp; } int result = tmp & 0x7f; if ((tmp = m_pBuffer.readInt8()) < 128) { result |= tmp << 7; } else { result |= (tmp & 0x7f) << 7; if ((tmp = m_pBuffer.readInt8()) < 128) { result |= tmp << 14; } else { result |= (tmp & 0x7f) << 14; if ((tmp = m_pBuffer.readInt8()) < 128) { result |= tmp << 21; } else { result |= (tmp & 0x7f) << 21; result |= (tmp = m_pBuffer.readInt8()) << 28; if (tmp >= 128) { for (int i = 0; i < 5; i++) { if (m_pBuffer.readInt8() < 128) { return (uint)result; } } throw new InvalidCastException(); } } } } return (uint)result; } protected uint readVarint32ByteToSbyte() { byte b = m_pBuffer.readInt8(); sbyte sb; unchecked { sb = (sbyte)b; } int tmp = sb; if (tmp < 128) { return (uint)tmp; } int result = tmp & 0x7f; if ((tmp = m_pBuffer.readInt8()) < 128) { result |= tmp << 7; } else { result |= (tmp & 0x7f) << 7; if ((tmp = m_pBuffer.readInt8()) < 128) { result |= tmp << 14; } else { result |= (tmp & 0x7f) << 14; if ((tmp = m_pBuffer.readInt8()) < 128) { result |= tmp << 21; } else { result |= (tmp & 0x7f) << 21; result |= (tmp = m_pBuffer.readInt8()) << 28; if (tmp >= 128) { for (int i = 0; i < 5; i++) { if (m_pBuffer.readInt8() < 128) { return (uint)result; } } throw new InvalidCastException(); } } } } return (uint)result; } protected void writeVarint64Byte(UInt64 value) { while (value > 127) { writeInt8((byte) ((value & 0x7F) | 0x80)); value >>= 7; } while (value > 127) { writeInt8((byte)((value & 0x7F) | 0x80)); value >>= 7; } writeInt8((byte)value); } protected ulong readVarint64Byte() { int shift = 0; ulong result = 0; while (shift < 64) { byte b = m_pBuffer.readInt8(); result |= (ulong)(b & 0x7F) << shift; if ((b & 0x80) == 0) { return result; } shift += 7; } throw new InvalidCastException(); } public string readVarintString() { Int16 nStrLen = 0; nStrLen = readVarint16(); byte[] b = m_pBuffer.readBytes(nStrLen); string s = System.Text.Encoding.UTF8.GetString(b); return s; } public void writeVarintString(string s) { byte[] val = System.Text.Encoding.UTF8.GetBytes(s); short len = (short)val.Length; writeVarint16(len); m_pBuffer.writeBytes(val); } } }
WebDownloader类
using System; using System.Collections.Generic; using System.Collections; using UnityEngine; using System.IO; using System.Threading; using System.Diagnostics; using System.Net; public class DownFileInfo { public string url; public string filePath; public string md5; } public class ProgressInfo { } public class WebDownloader { public float progrsss; private Stopwatch sw = new Stopwatch(); //线程 private Thread thread; //需要下载 private Queue<DownFileInfo> _downQueue = new Queue<DownFileInfo>(); //正在下载的文件信息 private Dictionary<string,string> _downloading = new Dictionary<string,string>(); public void StartDwonload() { thread = new Thread(delegate() { while (true) { _Download(); } }); thread.Start(); } private void _Download() { lock (_downQueue) { if (_downQueue.Count > 0) { DownFileInfo fileInfo = _downQueue.Dequeue(); try { using (WebClient client = new WebClient()) { sw.Start(); client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged); client.DownloadFileAsync(new System.Uri(fileInfo.url), fileInfo.filePath); } } catch (Exception ex) { UnityEngine.Debug.LogError(ex.Message); } } } } private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) { string value = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00")); UnityEngine.Debug.Log(value); if (e.ProgressPercentage == 100 && e.BytesReceived == e.TotalBytesToReceive) { sw.Reset(); } } public void AddDwonloadTask(string url,string filePath,string md5) { DownFileInfo fileInfo = new DownFileInfo(); fileInfo.url = url; fileInfo.filePath = filePath; fileInfo.md5 = md5; lock (_downQueue) { _downQueue.Enqueue(fileInfo); } } public void CheckMd5() { } }
原文:https://www.cnblogs.com/makeamericagreatagain/p/14312060.html