• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > C#使用Protocol Buffer(ProtoBuf)进行Unity中的Socket通信

C#使用Protocol Buffer(ProtoBuf)进行Unity中的Socket通信

作者:灵犀的博客 字体:[增加 减小] 来源:互联网 时间:2017-05-28

灵犀的博客 通过本文主要向大家介绍了马桶c的个人空间,c语言,欲情 c max,维生素c,奔驰c200等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

首先来说一下本文中例子所要实现的功能:

  • 基于ProtoBuf序列化对象
  • 使用Socket实现时时通信
  • 数据包的编码和解码

下面来看具体的步骤:

一、Unity中使用ProtoBuf

导入DLL到Unity中,
创建网络传输的模型类:

using System;
using ProtoBuf;

//添加特性,表示可以被ProtoBuf工具序列化
[ProtoContract]
public class NetModel {
 //添加特性,表示该字段可以被序列化,1可以理解为下标
 [ProtoMember(1)] 
 public int ID;
 [ProtoMember(2)]
 public string Commit;
 [ProtoMember(3)]
 public string Message;
}

using System;
using ProtoBuf;
 
//添加特性,表示可以被ProtoBuf工具序列化
[ProtoContract]
public class NetModel {
 //添加特性,表示该字段可以被序列化,1可以理解为下标
 [ProtoMember(1)] 
 public int ID;
 [ProtoMember(2)]
 public string Commit;
 [ProtoMember(3)]
 public string Message;
}

</div>

在Unity中添加测试脚本,介绍ProtoBuf工具的使用。

using System;
using System.IO;

public class Test : MonoBehaviour {

 void Start () {
  //创建对象
  NetModel item = new NetModel(){ID = 1, Commit = "LanOu", Message = "Unity"};
  //序列化对象
  byte[] temp = Serialize(item);
  //ProtoBuf的优势一:小
  Debug.Log(temp.Length);
  //反序列化为对象
  NetModel result = DeSerialize(temp);
  Debug.Log(result.Message);

 }

 // 将消息序列化为二进制的方法
 // < param name="model">要序列化的对象< /param>
 private byte[] Serialize(NetModel model)
 {
  try {
   //涉及格式转换,需要用到流,将二进制序列化到流中
   using (MemoryStream ms = new MemoryStream()) {
    //使用ProtoBuf工具的序列化方法
    ProtoBuf.Serializer.Serialize<NetModel> (ms, model);
    //定义二级制数组,保存序列化后的结果
    byte[] result = new byte[ms.Length];
    //将流的位置设为0,起始点
    ms.Position = 0;
    //将流中的内容读取到二进制数组中
    ms.Read (result, 0, result.Length);
    return result;
   }
  } catch (Exception ex) {
   Debug.Log ("序列化失败: " + ex.ToString());
   return null;
  }
 }

 // 将收到的消息反序列化成对象
 // < returns>The serialize.< /returns>
 // < param name="msg">收到的消息.</param>
 private NetModel DeSerialize(byte[] msg)
 {
  try {
   using (MemoryStream ms = new MemoryStream()) {
    //将消息写入流中
    ms.Write (msg, 0, msg.Length);
    //将流的位置归0
    ms.Position = 0;
    //使用工具反序列化对象
    NetModel result = ProtoBuf.Serializer.Deserialize<NetModel> (ms);
    return result;
   }
  } catch (Exception ex) {  
    Debug.Log("反序列化失败: " + ex.ToString());
    return null;
  }
 }
}

using System;
using System.IO;
 
public class Test : MonoBehaviour {
 
 void Start () {
  //创建对象
  NetModel item = new NetModel(){ID = 1, Commit = "LanOu", Message = "Unity"};
  //序列化对象
  byte[] temp = Serialize(item);
  //ProtoBuf的优势一:小
  Debug.Log(temp.Length);
  //反序列化为对象
  NetModel result = DeSerialize(temp);
  Debug.Log(result.Message);
 
 }
 
 // 将消息序列化为二进制的方法
 // < param name="model">要序列化的对象< /param>
 private byte[] Serialize(NetModel model)
 {
  try {
   //涉及格式转换,需要用到流,将二进制序列化到流中
   using (MemoryStream ms = new MemoryStream()) {
    //使用ProtoBuf工具的序列化方法
    ProtoBuf.Serializer.Serialize<NetModel> (ms, model);
    //定义二级制数组,保存序列化后的结果
    byte[] result = new byte[ms.Length];
    //将流的位置设为0,起始点
    ms.Position = 0;
    //将流中的内容读取到二进制数组中
    ms.Read (result, 0, result.Length);
    return result;
   }
  } catch (Exception ex) {
   Debug.Log ("序列化失败: " + ex.ToString());
   return null;
  }
 }
 
 // 将收到的消息反序列化成对象
 // < returns>The serialize.< /returns>
 // < param name="msg">收到的消息.</param>
 private NetModel DeSerialize(byte[] msg)
 {
  try {
   using (MemoryStream ms = new MemoryStream()) {
    //将消息写入流中
    ms.Write (msg, 0, msg.Length);
    //将流的位置归0
    ms.Position = 0;
    //使用工具反序列化对象
    NetModel result = ProtoBuf.Serializer.Deserialize<NetModel> (ms);
    return result;
   }
  } catch (Exception ex) {  
    Debug.Log("反序列化失败: " + ex.ToString());
    return null;
  }
 }
}

</div>

二、Unity中使用Socket实现时时通信

通信应该实现的功能:

  • 服务器可以时时监听多个客户端
  • 服务器可以时时监听某一个客户端消息
  • 服务器可以时时给某一个客户端发消息
  • 首先我们需要定义一个客户端对象
using System;
using System.Net.Sockets;

// 表示一个客户端
public class NetUserToken {
 //连接客户端的Socket
 public Socket socket;
 //用于存放接收数据
 public byte[] buffer;

 public NetUserToken()
 {
  buffer = new byte[1024];
 }

 // 接受消息
 // < param name="data">Data.< /param>
 public void Receive(byte[] data)
 {
  UnityEngine.Debug.Log("接收到消息!");
 }

 // 发送消息
 //< param name="data">Data.< /param>
 public void Send(byte[] data)
 {  

 }
}

using System;
using System.Net.Sockets;
 
// 表示一个客户端
public class NetUserToken {
 //连接客户端的Socket
 public Socket socket;
 //用于存放接收数据
 public byte[] buffer;
 
 public NetUserToken()
 {
  buffer = new byte[1024];
 }
 
 // 接受消息
 // < param name="data">Data.< /param>
 public void Receive(byte[] data)
 {
  UnityEngine.Debug.Log("接收到消息!");
 }
 
 // 发送消息
 //< param name="data">Data.< /param>
 public void Send(byte[] data)
 {  
 
 }
}

</div>


然后实现我们的服务器代码

using System.Collections;
using System.Collections.Generic;
using System.Net;
using System;
using System.Net.Sockets;

public class NetServer{
 //单例脚本
 public static readonly NetServer Instance = new NetServer();
 //定义tcp服务器
 private Socket server;
 private int maxClient = 10;
 //定义端口
 private int port = 35353;
 //用户池
 private Stack<NetUserToken> pools;
 private NetServer()
 {
  //初始化socket
  server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  server.Bind(new IPEndPoint(IPAddress.Any, port));

 }

 //开启服务器
 public void Start()
 {
  server.Listen(maxClient);
  UnityEngine.Debug.Log("Server OK!");
  //实例化客户端的用户池
  pools = new Stack<NetUserToken>(maxClient);
  for(int i = 0; i < maxClient; i++)
  {
   NetUserToken usertoken = new NetUserToken();
   pools.Push(usertoken);
  }
  //可以异步接受客户端, BeginAccept函数的第一个参数是回调函数,当有客户端连接的时候自动调用
  server.BeginAccept (AsyncAccept, null);
 }

 //回调函数, 有客户端连接的时候会自动调用此方法
 private void AsyncAccept(IAsyncResult result)
 {
  try {
   //结束监听,同时获取到客户端
   Socket client = server.EndAccept(result);
   UnityEngine.Debug.Log("有客户端连接");
   //来了一个客户端
   NetUserToken userToken = pools.Pop();
   userToken.socket = client;
   //客户端连接之后,可以接受客户端消息
   BeginReceive(userToken);

   //尾递归,再次监听是否还有其他客户端连入
   server.BeginAccept(AsyncAccept, null);
  } catch (Exception ex) {
   UnityEngine.Debug.Log(ex.ToString());
  }
 }

 //异步监听消息
 private void BeginReceive(NetUserToken userToken)
 {
  try {
   //异步方法
   userToken.socket.BeginReceive(userToken.buffer, 0, userToken.buffer.Length, SocketFlags.None,
           EndReceive, userToken);
  } catch (Exception ex) {
   UnityEngine.Debug.Log(ex.ToString());
  }
 }

 //监听到消息之后调用的函数
 private void EndReceive(IAsyncResult result)
 {
  try {
 



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C#利用ReportViewer生成报表
  • C#基于正则去掉注释的方法示例
  • C#中new的用法及与override的区别分析
  • C#实现两个richtextbox控件滚动条同步滚动的简单方法
  • C# for循环的经典案例集锦
  • C#操作word的方法示例
  • C#使用WebClient登录网站并抓取登录后的网页信息实现方法
  • C# WinForm制作异形窗体与控件的方法
  • C#实现Excel表数据导入Sql Server数据库中的方法
  • C#使用NPOI上传excel

相关文章

  • 2017-05-28C#中try...catch的使用与常见面试题分享
  • 2017-05-28C#获取web.config配置文件内容的方法
  • 2017-05-28C#的回调机制浅析
  • 2017-05-28C#给图片加水印的简单实现方法
  • 2017-05-28C#读取目录下所有指定类型文件的方法
  • 2017-05-28C#配置文件Section节点处理总结
  • 2017-05-28C#编程获取IP地址的方法示例
  • 2017-05-28C#导出网站功能实例代码讲解
  • 2017-05-28c#动态加载卸载DLL的方法
  • 2017-05-28C#基于正则去掉注释的方法示例

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C#中设置textbox限制条件的方法
    • C#判断字符串是否是int/double(实例)
    • C#基本打印事件用法实例
    • C#动态加载dll扩展系统功能的方法
    • C#为配置文件加密的实现方法
    • C#求解哈夫曼树,实例代码
    • 详解TreeView绑定数据库
    • C#预处理器指令的用法实例分析
    • C#使用itextsharp生成PDF文件的实现代码
    • winform 实现选择文件和选择文件夹对话框的简单实例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有