扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
这篇文章主要介绍了socket传输protobuf字节流的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
创新互联一直通过网站建设和网站营销帮助企业获得更多客户资源。 以"深度挖掘,量身打造,注重实效"的一站式服务,以成都网站设计、成都网站建设、外贸网站建设、移动互联产品、成都营销网站建设服务为核心业务。10年网站制作的经验,使用新网站建设技术,全新开发出的标准网站,不但价格便宜而且实用、灵活,特别适合中小公司网站制作。网站管理系统简单易用,维护方便,您可以完全操作网站资料,是中小公司快速网站建设的选择。
使用多线程收发消息
//创建消息数据模型 2 //正式项目中,消息的结构一般是消息长度+消息id+消息主体内容 3 public class Message 4 { public IExtensible protobuf; public int messageId; 7 } 8 9 public class SocketClientTemp : MonoBehaviour 10 { 11 const int packageMaxLength = 1024; 12 13 Socket mSocket; 14 Thread threadSend; 15 Thread threadRecive; 16 QueueallMessages = new Queue (); 17 Queue sendQueue = new Queue (); public bool Init() 20 { 21 //创建一个socket对象 22 mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 23 return SocketConnection("此处是ip", 1111); 24 } 25 26 void Update() 27 { 28 AnalysisMessage(); 29 } 30 31 /// 32 /// 建立服务器连接 33 /// 34 /// 服务器的ip地址 35 /// 端口 36 bool SocketConnection(string ip, int port) 37 { 38 try 39 { 40 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ip), port); 41 //同步连接服务器,实际使用时推荐使用异步连接,处理方式会在下一篇讲断线重连时讲到 42 mSocket.Connect(ipep); 43 //连接成功后,创建两个线程,分别用于发送和接收消息 44 threadSend = new Thread(new ThreadStart(SendMessage)); 45 threadSend.Start(); 46 threadRecive = new Thread(new ThreadStart(ReceiveMessage)); 47 threadRecive.Start(); 48 return true; 49 } 50 catch (Exception e) 51 { 52 Debug.Log(e.ToString()); 53 Close(); 54 return false; 55 } } #region ...发送消息 59 ///60 /// 添加数据到发送队列 61 /// 62 /// 63 /// 64 public void AddSendMessageQueue(IExtensible protobufModel, int messageId) 65 { 66 sendQueue.Enqueue(BuildPackage(protobufModel, messageId)); 67 } void SendMessage() 70 { 71 //循环获取发送队列中第一个数据,然后发送到服务器 72 while (true) 73 { 74 if (sendQueue.Count == 0) 75 { 76 Thread.Sleep(100); 77 continue; 78 } 79 if (!mSocket.Connected) 80 { 81 Close(); 82 break; 83 } 84 else 85 Send(sendQueue.Peek()); //发送队列中第一条数据 86 } 87 } 88 89 void Send(byte[] bytes) 90 { 91 try 92 { 93 mSocket.Send(bytes, SocketFlags.None); 94 //发送成功后,从发送队列中移除已发送的消息 95 sendQueue.Dequeue(); 96 } 97 catch (SocketException e) 98 { 99 //如果错误码为10035,说明服务器缓存区满了,所以等100毫秒再次发送100 if (e.NativeErrorCode == 10035)101 {102 Thread.Sleep(100);103 Send(bytes);104 }105 else106 Debug.Log(e.ToString());107 }108 }109 #endregion110 111 #region ...接收消息112 ///113 /// 解析收到的消息114 /// 115 void AnalysisMessage()116 {117 while (allMessages.Count > 0)118 {119 int id = allMessages.Dequeue().messageId;120 switch (id)121 {122 //根据消息id做不同的处理123 }124 }125 }126 127 ///128 /// 接收数据129 /// 130 void ReceiveMessage()131 {132 while (true)133 {134 if (!mSocket.Connected)135 break;136 byte[] recvBytesHead = GetBytesReceive(4);137 int bodyLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(recvBytesHead, 0));138 byte[] recvBytesBody = GetBytesReceive(bodyLength);139 140 byte[] messageId = new byte[4];141 Array.Copy(recvBytesBody, 0, messageId, 0, 4);142 byte[] messageBody = new byte[bodyLength - 4];143 Array.Copy(recvBytesBody, 4, messageBody, 0, bodyLength - 4);144 145 if (BitConverter.IsLittleEndian)146 Array.Reverse(messageId);147 FillAllPackages(BitConverter.ToInt32(messageId, 0), messageBody);148 } } ///152 /// 填充接收消息队列153 /// 154 /// 155 /// 156 void FillAllPackages(int messageId, byte[] messageBody)157 {158 switch (messageId)159 {160 //根据消息id处理消息,并添加到接收消息队列161 case 1:162 allMessages.Enqueue(new Message() 163 {164 protobuf = ProtobufSerilizer.DeSerialize(messageBody), 165 messageId = messageId 166 });167 break;168 }169 }170 171 /// 172 /// 接收数据并处理173 /// 174 /// 175 ///176 byte[] GetBytesReceive(int length)177 {178 byte[] recvBytes = new byte[length];179 while (length > 0)180 {181 byte[] receiveBytes = new byte[length < packageMaxLength ? length : packageMaxLength];182 int iBytesBody = 0;183 if (length >= receiveBytes.Length)184 iBytesBody = mSocket.Receive(receiveBytes, receiveBytes.Length, 0);185 else186 iBytesBody = mSocket.Receive(receiveBytes, length, 0);187 receiveBytes.CopyTo(recvBytes, recvBytes.Length - length);188 length -= iBytesBody;189 }190 return recvBytes;191 }192 #endregion193 194 /// 195 /// 构建消息数据包196 /// 197 /// 198 /// 199 byte[] BuildPackage(IExtensible protobufModel, int messageId)200 {201 byte[] b;202 if (protobufModel != null)203 b = ProtobufSerilizer.Serialize(protobufModel);204 else205 b = new byte[0];206 //消息长度(int数据,长度4) + 消息id(int数据,长度4) + 消息主体内容207 ByteBuffer buf = ByteBuffer.Allocate(b.Length + 4 + 4);208 //消息长度 = 消息主体内容长度 + 消息id长度209 buf.WriteInt(b.Length + 4);210 buf.WriteInt(messageId);211 212 if (protobufModel != null)213 buf.WriteBytes(b);214 return buf.GetBytes();215 }216 217 void OnDestroy()218 {219 //停止运行后,如果不关闭socket多线程,再次运行时,unity会卡死220 Close();221 }222 223 ///224 /// 关闭socket,终止线程225 /// 226 public void Close()227 {228 if (mSocket != null)229 {230 //微软官方推荐在关闭socket前先shutdown,但是经过测试,发现网络断开后,shutdown会无法执行231 if (mSocket.Connected)232 mSocket.Shutdown(SocketShutdown.Both);233 mSocket.Close();234 mSocket = null;235 }236 //关闭线程237 if (threadSend != null)238 threadSend.Abort();239 if (threadRecive != null)240 threadRecive.Abort();241 threadSend = null;242 threadRecive = null;243 }244 }
到这里,使用socket处理消息的收发就基本结束了。
感谢你能够认真阅读完这篇文章,希望小编分享的“socket传输protobuf字节流的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持创新互联,关注创新互联行业资讯频道,更多相关知识等着你来学习!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流