C#Like是Unity的热更方案,使用纯C#语言写出可以热更新的代码,就像可以在所有平台使用DLL(动态链接库)文件一样.遵从KISS设计原则,让用户轻松构建或升级成Unity的热更新项目.
简介
本篇主要介绍C#Like支持的长链接Socket和WebSocket,免费版和完整版都支持,示范代码差别在于完整版的使用了自定义get/set和使用了switch语句.
- Socket: 对应内置的类CSL_ClientSocket
- WebSocket: 对应内置的类CSL_ClientWebSocket
- 注意在WebGL平台下只支持WebSocket,如果你的应用包含WebGL平台,必须包含WebSocket,如示范代码一样使用.
这里仅示范客户端的主接口代码,更加详尽的用法详见 Unity热更新方案C#Like(廿一)-详解KissFrameworkServer:对应的示范例子和官网所用的服务器框架
C#Like免费版:
示范代码如下:
using System.Collections.Generic;
using UnityEngine;
namespace CSharpLike
{
/// <summary>
/// 如何使用Socket和WebSocket的示范.
/// 所有的函数均在主线程内运行.
/// </summary>
public class SampleSocket
{
/// <summary>
/// 使用WebSocket还是Socket.
/// WebGL将强制使用WebSocket!
/// 你应该调用ampleSocket.Instance前设置它.
/// </summary>
public static bool usingWebSocket = false;
/// <summary>
/// WebSocket的URI(支持WSS).
/// 你应该调用ampleSocket.Instance前设置它.
/// </summary>
public static string webSocketURI = "ws://127.0.0.1:9000";
/// <summary>
/// Socket的Host.
/// 你应该调用ampleSocket.Instance前设置它.
/// </summary>
public static string socketHost = "127.0.0.1";
/// <summary>
/// Socket的端口.
/// 你应该调用ampleSocket.Instance前设置它.
/// </summary>
public static int socketPort = 9001;
/// <summary>
/// RSA公钥,使用Socket的情况下.
/// 你应该调用SampleSocket.Instance前设置它.
/// 你在Unity编辑器里的C#Like设置面板点击'Generate RSA'按钮后,
/// 你可以在Assets/C#Like/Editor/RSAPublicKey.txt找到.
/// 如果你不想使用安全模式,你可以设置为空白.
/// 安全模式:先通过RSA发送AES密码到服务器,然后客户端和服务器之间使用AES加密传输.
/// </summary>
public static string socketRSAPublicKey = "";
/// <summary>
/// WebSocket/Socket对象.
/// 在使用它之前, 你应该先设置
/// usingWebSocket/webSocketURI/socketHost/socketPort的值
/// </summary>
public static SampleSocket Instance
{
get;
set;
}
/// <summary>
/// 初始化SampleSocket对象,你必须先初始化它,因为免费版不支持自定义get/set
/// </summary>
public static void Init()
{
if (Instance == null)
Instance = new SampleSocket();
}
/// <summary>
/// WebSocket/Socket是否已连接.
/// </summary>
public bool IsConnected()
{
if (clientWebSocket != null)
return clientWebSocket.IsConnected;
else if (clientSocket != null)
return clientSocket.IsConnected;
return false;
}
/// <summary>
/// 当WebSocket/Socket连接上后的事件
/// </summary>
void OnOpen()
{
Debug.Log("SampleSocket:OnOpen");
}
/// <summary>
/// 当WebSocket/Socket关闭后的事件
/// </summary>
void OnClose(string msg)
{
Debug.Log("SampleSocket:OnClose:" + msg);
}
/// <summary>
/// 当WebSocket/Socket发生错误的事件
/// </summary>
void OnError(string msg)
{
//just print the message
Debug.LogError("SampleSocket:OnError:" + msg);
}
public SampleSocket()
{
Debug.Log("Application.platform=" + Application.platform);
//WebGL平台只支持WebSocket
if (usingWebSocket || Application.platform == RuntimePlatform.WebGLPlayer)
{
Debug.Log("usingWebSocket=true");
//初始化WebSocket
GameObject go = new GameObject("ClientWebSocket");
clientWebSocket = go.AddComponent<CSL_ClientWebSocket>();
//设置WebSocket的回调
clientWebSocket.onOpen += OnOpen;
clientWebSocket.onClose += OnClose;
clientWebSocket.onError += OnError;
clientWebSocket.onMessage += OnMessage;
//设置Uri
clientWebSocket.SetUri(webSocketURI);
开始连接到服务器
//clientWebSocket.Connect();
}
else
{
Debug.Log("usingWebSocket=false");
//初始化Socket
GameObject go = new GameObject("ClientSocket");
clientSocket = go.AddComponent<CSL_ClientSocket>();
//设置Socket的回调
clientSocket.onOpen += OnOpen;
clientSocket.onClose += OnClose;
clientSocket.onError += OnError;
clientSocket.onMessage += OnMessage;
clientSocket.Host = socketHost;
clientSocket.Port = socketPort;
clientSocket.RSAPublicKey = socketRSAPublicKey;
开始连接到服务器
//clientSocket.Connect();
}
}
/// <summary>
/// 关闭当前WebSocket/Socket的连接
/// </summary>
public void Close()
{
if (clientWebSocket != null)
clientWebSocket.Close();
else if (clientSocket != null)
clientSocket.Close();
else
Debug.LogError("SampleSocket : Close : clientWebSocket and clientSocket are both null.");
}
/// <summary>
/// 连接WebSocket/Socket
/// </summary>
public void Connect()
{
if (clientWebSocket != null)
clientWebSocket.Connect();
else if (clientSocket != null)
clientSocket.Connect();
else
Debug.LogError("SampleSocket : Connect : clientWebSocket and clientSocket are both null.");
}
/// <summary>
/// 发送JSON对象到服务器
/// </summary>
/// <param name="jsonData">将要发到服务器的JSON对象</param>
public void Send(JSONData jsonData)
{
if (clientWebSocket != null)
clientWebSocket.Send(jsonData);
else if (clientSocket != null)
clientSocket.Send(jsonData);
else
Debug.LogError("SampleSocket : Send : clientWebSocket and clientSocket are both null.");
}
/// <summary>
/// 收到服务器的JSON对象
/// </summary>
/// <param name="jsonData">服务器发过来的JSON对象</param>
void OnMessage(JSONData jsonData)
{
if (Application.isEditor)
Debug.Log("SampleSocket : OnMessage : " + jsonData.ToJson(true));
//这里处理不同的命令
//int packetType = jsonData["packetType"];//如果设置JSONData.packetIsInteger为true
string packetType = jsonData["packetType"];
//免费版不能使用枚举,我们采用字符串.
//免费版不能使用switch语句,我们使用if-else代替,如果类型很多的话会有性能问题
if (packetType == "CB_Error")
{
Debug.LogError(jsonData["error"]);//我们这里打印一个错误信息
}
else if (packetType == "CB_Tips")
{
Debug.Log(jsonData["tips"]);//我们这里打印一个提示信息
}
else
{
Debug.LogError("SampleSocket : OnMessage : Unknown packetType : " + packetType);
}
}
/// <summary>
/// 销毁WebSocket/Socket对象
/// </summary>
public void Destroy()
{
if (clientWebSocket != null)
GameObject.Destroy(clientWebSocket.gameObject);
else if (clientSocket != null)
GameObject.Destroy(clientSocket.gameObject);
clientWebSocket = null;
clientSocket = null;
Instance = null;
}
CSL_ClientWebSocket clientWebSocket = null;
CSL_ClientSocket clientSocket = null;
}
}
C#Like完整版:
示范代码如下:
using UnityEngine;
namespace CSharpLike
{
/// <summary>
/// 如何使用Socket和WebSocket的示范.
/// 所有的函数均在主线程内运行.
/// </summary>
public class SampleSocket
{
/// <summary>
/// 使用WebSocket还是Socket.
/// WebGL将强制使用WebSocket!
/// 你应该调用ampleSocket.Instance前设置它.
/// </summary>
public static bool usingWebSocket = false;
/// <summary>
/// WebSocket的URI(支持WSS).
/// 你应该调用ampleSocket.Instance前设置它.
/// </summary>
public static string webSocketURI = "ws://127.0.0.1:9000";
/// <summary>
/// Socket的Host.
/// 你应该调用ampleSocket.Instance前设置它.
/// </summary>
public static string socketHost = "127.0.0.1";
/// <summary>
/// Socket的端口.
/// 你应该调用ampleSocket.Instance前设置它.
/// </summary>
public static int socketPort = 9001;
/// <summary>
/// RSA公钥,使用Socket的情况下.
/// 你应该调用SampleSocket.Instance前设置它.
/// 你在Unity编辑器里的C#Like设置面板点击'Generate RSA'按钮后,
/// 你可以在Assets/C#Like/Editor/RSAPublicKey.txt找到.
/// 如果你不想使用安全模式,你可以设置为空白.
/// 安全模式:先通过RSA发送AES密码到服务器,然后客户端和服务器之间使用AES加密传输.
/// </summary>
public static string socketRSAPublicKey = "";
/// <summary>
/// WebSocket/Socket对象.
/// 在使用它之前, 你应该先设置
/// usingWebSocket/webSocketURI/socketHost/socketPort的值
/// </summary>
public static SampleSocket Instance
{
get
{
if (mInstance == null)
mInstance = new SampleSocket();
return mInstance;
}
}
/// <summary>
/// WebSocket/Socket是否已连接.
/// </summary>
public bool IsConnected
{
get
{
if (clientWebSocket != null)
return clientWebSocket.IsConnected;
else if (clientSocket != null)
return clientSocket.IsConnected;
return false;
}
}
/// <summary>
/// 当WebSocket/Socket连接上后的事件
/// </summary>
void OnOpen()
{
Debug.Log("SampleSocket:OnOpen");
}
/// <summary>
/// 当WebSocket/Socket关闭后的事件
/// </summary>
void OnClose(string msg)
{
Debug.Log("SampleSocket:OnClose:" + msg);
}
/// <summary>
/// 当WebSocket/Socket发生错误的事件
/// </summary>
void OnError(string msg)
{
//just print the message
Debug.LogError("SampleSocket:OnError:" + msg);
}
public SampleSocket()
{
Debug.Log("Application.platform=" + Application.platform);
//WebGL平台只支持WebSocket
if (usingWebSocket || Application.platform == RuntimePlatform.WebGLPlayer)
{
Debug.Log("usingWebSocket=true");
//初始化WebSocket
GameObject go = new GameObject("ClientWebSocket");
clientWebSocket = go.AddComponent<CSL_ClientWebSocket>();
//设置WebSocket的回调
clientWebSocket.onOpen += OnOpen;
clientWebSocket.onClose += OnClose;
clientWebSocket.onError += OnError;
clientWebSocket.onMessage += OnMessage;
//设置Uri
clientWebSocket.SetUri(webSocketURI);
开始连接到服务器
//clientWebSocket.Connect();
}
else
{
Debug.Log("usingWebSocket=false");
//初始化Socket
GameObject go = new GameObject("ClientSocket");
clientSocket = go.AddComponent<CSL_ClientSocket>();
//设置Socket的回调
clientSocket.onOpen += OnOpen;
clientSocket.onClose += OnClose;
clientSocket.onError += OnError;
clientSocket.onMessage += OnMessage;
clientSocket.Host = socketHost;
clientSocket.Port = socketPort;
clientSocket.RSAPublicKey = socketRSAPublicKey;
开始连接到服务器
//clientSocket.Connect();
}
}
/// <summary>
/// 关闭当前WebSocket/Socket的连接
/// </summary>
public void Close()
{
if (clientWebSocket != null)
clientWebSocket.Close();
else if (clientSocket != null)
clientSocket.Close();
else
Debug.LogError("SampleSocket : Close : clientWebSocket and clientSocket are both null.");
}
/// <summary>
/// 连接WebSocket/Socket
/// </summary>
public void Connect()
{
if (clientWebSocket != null)
clientWebSocket.Connect();
else if (clientSocket != null)
clientSocket.Connect();
else
Debug.LogError("SampleSocket : Connect : clientWebSocket and clientSocket are both null.");
}
/// <summary>
/// 发送JSON对象到服务器
/// </summary>
/// <param name="jsonData">将要发到服务器的JSON对象</param>
public void Send(JSONData jsonData)
{
if (clientWebSocket != null)
clientWebSocket.Send(jsonData);
else if (clientSocket != null)
clientSocket.Send(jsonData);
else
Debug.LogError("SampleSocket : Send : clientWebSocket and clientSocket are both null.");
}
/// <summary>
/// 收到服务器的JSON对象
/// </summary>
/// <param name="jsonData">服务器发过来的JSON对象</param>
void OnMessage(JSONData jsonData)
{
if (Application.isEditor)
Debug.Log("SampleSocket : OnMessage : " + jsonData.ToJson(true));
//这里处理不同的命令
switch ((PacketType)jsonData.GetPacketType(typeof(PacketType)))
{
case PacketType.CB_Error:
Debug.LogError(jsonData["error"]);//我们这里打印一个错误信息
break;
case PacketType.CB_Tips:
Debug.Log(jsonData["tips"]);//我们这里打印一个提示信息
break;
default:
Debug.LogError("SampleSocket : OnMessage : Unknown packetType : " + jsonData["packetType"]);
break;
}
}
/// <summary>
/// 销毁WebSocket/Socket对象
/// </summary>
public void Destroy()
{
if (clientWebSocket != null)
GameObject.Destroy(clientWebSocket.gameObject);
else if (clientSocket != null)
GameObject.Destroy(clientSocket.gameObject);
clientWebSocket = null;
clientSocket = null;
mInstance = null;
}
static SampleSocket mInstance;
CSL_ClientWebSocket clientWebSocket = null;
CSL_ClientSocket clientSocket = null;
}
}
本系列文章导读:
- Unity热更新方案C#Like(一)-序言
- Unity热更新方案C#Like(二)-导出官方示范的例子,确认方案可行性
- Unity热更新方案C#Like(三)-详解支持的C#特性:类
- Unity热更新方案C#Like(四)-详解支持的C#特性:委托和Lambda
- Unity热更新方案C#Like(五)-详解支持的C#特性:运算表达式
- Unity热更新方案C#Like(六)-详解支持的C#特性:循环语法
- Unity热更新方案C#Like(七)-详解支持的C#特性:get/set访问器
- Unity热更新方案C#Like(八)-详解支持的C#特性:多线程
- Unity热更新方案C#Like(九)-详解支持的C#特性:Using和命名空间
- Unity热更新方案C#Like(十)-详解支持的C#特性:宏和区域
- Unity热更新方案C#Like(十一)-详解支持的C#特性:枚举
- Unity热更新方案C#Like(十二-详解支持的C#特性:参数修饰符
- Unity热更新方案C#Like(十三)-详解支持的C#特性:函数重载和默认参数
- Unity热更新方案C#Like(十四)-详解支持的C#特性:异常处理
- Unity热更新方案C#Like(十五)-详解支持的C#特性:关键字:unsafe typeof nameof $ @ #pragma #warning #error
- Unity热更新方案C#Like(十六)-详解支持的C#特性:其他杂项:初始值设定项,表达式主体,内联变量声明
- Unity热更新方案C#Like(十七)-详解支持的长链接Socket和WebSocket
- Unity热更新方案C#Like(十八)-详解如何和Unity交互
- Unity热更新方案C#Like(十九)-详解KissJSON:唯一可以在本热更新框架使用的JSON库
- Unity热更新方案C#Like(二十)-详解KissCSV:一个简易实用的CSV表格读取方式
- Unity热更新方案C#Like(廿一)-详解KissFrameworkServer:对应的示范例子和官网所用的服务器框架
- Unity热更新方案C#Like(廿二)-详解内置的例子C#Like Demo:飞机大战,简易聊天室,简易账号/物品/邮件系统
- Unity热更新方案C#Like(廿三)-实战:示范如何把Unity官方免费例子Tanks! Tutorial转成可热更新项目
- Unity热更新方案C#Like(廿四)-实战:示范如何把Unity官方免费例子Platformer Microgame转成可热更新项目
- Unity热更新方案C#Like(廿五)-实战:示范如何建立初始包CSharpLikeFreeDemo项目
- Unity热更新方案C#Like(廿六)-(可选)详解免费版的演示如何升级到完整版的演示