search
HomeBackend DevelopmentC#.Net TutorialExample introduction of socket transmission protobuf byte stream
Example introduction of socket transmission protobuf byte streamJun 29, 2017 pm 02:31 PM
protobufsocketunitytransmissionexplorer

The previous article talked about data processing. This article mainly talks about using multi-threads to send and receive messages.

//创建消息数据模型  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<Message> allMessages = new Queue<Message>(); 17     
  Queue<byte[]> sendQueue = new Queue<byte[]>();
  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     /// <summary> 32     /// 建立服务器连接 33     /// </summary> 34     
   /// <param name="ip">服务器的ip地址</param> 35     /// <param name="port">端口</param> 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     
 /// <summary> 60     /// 添加数据到发送队列 61     
 /// </summary> 62     /// <param name="protobufModel"></param> 63     
 /// <param name="messageId"></param> 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     /// <summary>113     /// 解析收到的消息114     
 /// </summary>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     
 /// <summary>128     /// 接收数据129     /// </summary>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         
 }    
 }
  /// <summary>152    
   /// 填充接收消息队列153     /// </summary>154     
   /// <param name="messageId"></param>155     /// <param name="messageBody"></param>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<TestTemp>(messageBody), 
165                     
messageId = messageId 
166                 });167                
 break;168         }169     }170 171     
/// <summary>172     /// 接收数据并处理173     
/// </summary>174     /// <param name="length"></param>175     
/// <returns></returns>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     /// <summary>195     /// 构建消息数据包196     
/// </summary>197     /// <param name="protobufModel"></param>198     /// <param name="messageId"></param>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     
 /// <summary>224     /// 关闭socket,终止线程225     /// </summary>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 }

At this point, using socket to process message sending and receiving is basically over. However, some In order to enhance the experience, the project may also add the function of disconnection and reconnection. This function will be discussed in the next article

The above is the detailed content of Example introduction of socket transmission protobuf byte stream. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Python的socket与socketserver怎么使用Python的socket与socketserver怎么使用May 28, 2023 pm 08:10 PM

一、基于TCP协议的socket套接字编程1、套接字工作流程先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束,使用以下Python代码实现:importso

PHP+Socket系列之IO多路复用及实现web服务器PHP+Socket系列之IO多路复用及实现web服务器Feb 02, 2023 pm 01:43 PM

本篇文章给大家带来了关于php+socket的相关知识,其中主要介绍了IO多路复用,以及php+socket如何实现web服务器?感兴趣的朋友下面一起来看一下,希望对大家有帮助。

怎么使用Spring Boot+Vue实现Socket通知推送怎么使用Spring Boot+Vue实现Socket通知推送May 27, 2023 am 08:47 AM

SpringBoot端第一步,引入依赖首先我们需要引入WebSocket所需的依赖,以及处理输出格式的依赖com.alibabafastjson1.2.73org.springframework.bootspring-boot-starter-websocket第二步,创建WebSocket配置类importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Config

php socket无法连接怎么办php socket无法连接怎么办Nov 09, 2022 am 10:34 AM

php socket无法连接的解决办法:1、检查php是否开启socket扩展;2、打开php.ini文件,检查“php_sockets.dll”是否被加载;3、取消“php_sockets.dll”的注释状态即可。

PHP+Socket系列之实现客户端与服务端数据传输PHP+Socket系列之实现客户端与服务端数据传输Feb 02, 2023 am 11:35 AM

本篇文章给大家带来了关于php+socket的相关知识,其中主要介绍了什么是socket?php+socket如何实现客户端与服务端数据传输?感兴趣的朋友下面一起来看一下,希望对大家有帮助。

unity发布出来的安卓apk该如何加密unity发布出来的安卓apk该如何加密May 13, 2023 am 11:10 AM

Unity3D程序的安全问题代码安全问题Unity3D程序的核心程序集文件Assembly-CSharp.dll是标准的.NET文件格式,附带了方法名、类名、类型定义等丰富的元数据信息,使用DnSpy等工具可以轻易地将其反编译和篡改,代码逻辑、类名和方法名等一览无余。代码逻辑一但被反编译,很容易滋生各种类型的外挂,破坏游戏平衡,如果代码逻辑中存在漏洞,也容易被挖掘和利用,可能对开发商造成无法预料的损失。资源安全问题Unity3D程序在编译打包阶段会通过Unity编辑器将资源打包成AssetBun

利用PHP和Socket实现实时文件传输技术研究利用PHP和Socket实现实时文件传输技术研究Jun 28, 2023 am 09:11 AM

随着互联网的发展,文件传输成为人们日常工作和娱乐中不可或缺的一部分。然而,传统的文件传输方式如邮件附件或文件分享网站存在一定的限制,无法满足实时性和安全性的需求。因此,利用PHP和Socket技术实现实时文件传输成为了一种新的解决方案。本文将介绍利用PHP和Socket技术实现实时文件传输的技术原理、优点和应用场景,并通过具体案例来演示该技术的实现方法。技术

C#中常见的网络通信和安全性问题及解决方法C#中常见的网络通信和安全性问题及解决方法Oct 09, 2023 pm 09:21 PM

C#中常见的网络通信和安全性问题及解决方法在当今互联网时代,网络通信已经成为了软件开发中必不可少的一部分。在C#中,我们通常会遇到一些网络通信的问题,例如数据传输的安全性、网络连接的稳定性等。本文将针对C#中常见的网络通信和安全性问题进行详细讨论,并提供相应的解决方法和代码示例。一、网络通信问题网络连接中断:网络通信过程中,可能会出现网络连接的中断,这会导致

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft