socket传输protobuf字节流的示例分析
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要介绍了socket传输protobuf字节流的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。使用多线程收发消息//
千家信息网最后更新 2026年11月01日socket传输protobuf字节流的示例分析
这篇文章主要介绍了socket传输protobuf字节流的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
使用多线程收发消息
//创建消息数据模型 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 Queue allMessages = 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字节流的示例分析"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!
消息
数据
长度
队列
服务器
线程
处理
服务
篇文章
主体
内容
示例
传输
分析
成功
再次
推荐
运行
不同
两个
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
咖啡网
互联网科技产业
互联网科技会
网络科技有限互联网
以房互联网科技
互联网科技股票
掌上梦互联网科技
狮子座互联网科技培训
互联网 新科技
互联网公司会议桌创意科技软装饰
阿里互联网科技公司
湖南诚度互联网科技有限公司
互联网科技和信息
华夏恒生互联网科技013171
工业互联网等科技实现智能化赋能
特约风豹互联网科技为什么扣费
互联网金融科技名词解释
锡山区互联网智能科技产品供应
绵阳真晨互联网科技有限公司
上海互联网科技园景观
互联网是不是新科技
北京互联网科技有限公司
奇酷互联网科技公司
世界互联网领先科技成果
互联网金融科技创新
互联网金融科技平台
宝灵互联网科技有限公司
科技类公司包括互联网吗
上海京穆互联网科技有限公司
高科技和互联网的现代国家