神刀安全网

Unity客户端与Netty服务器通信搭建(二):Unity客户端程序

前言

最近和几个同学一起做一个手游项目,虽然是单机,但是有检测新版本的需求,因此还是要搭建一个服务器来实现客户端检测更新的功能。在朋友的推荐下,我选择使用Netty的服务器架构,关于Netty的优点可以百度下,这里不再累赘。从没听过Netty到实现与Unity客户端的通信总共花了两天,其中遇到了很多坑,我将在这系列文章中复盘这两天的开发流程,给想要入门Unity客户端+Netty服务端通信的同学带下路,少走一些弯路。

参考文章:http://www.itstack.org/?post=18

一、开发环境搭建


我的开发环境
  • Mac OS 10.11.6
  • Unity 5.3.5 P6
  • 编程语言:C#

二、Unity客户端代码


Unity工程
Unity客户端与Netty服务器通信搭建(二):Unity客户端程序
工程截图.png

工程包含两个C#文件

  • nettyComponent.cs

    将nettyComponent.cs拖拽到Unity场景中的Gameobject即可

  • nettyClient.cs

    nettyClient.cs实现了:
    1.连接服务器
    2.网络检测
    3.失败重连

nettyComponent.cs

using UnityEngine; using System.Collections;  public class nettyComponent : MonoBehaviour {  public string IP = "127.0.0.1"; public int Port = 7397;  nettyClient client; mySocket mysocket;  // Use this for initialization void Start () {     //获得nettyClient实例     client = nettyClient.GetInstance (IP,Port); }   // Update is called once per frame void Update () {     if (Input.GetKeyDown (KeyCode.Escape))         client.Closed ();     } }

nettyClient.cs

using UnityEngine; using System.Collections;  using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Net; using System.Net.Sockets;  public class nettyClient {  public string IP = "127.0.0.1"; public int Port = 7397;  public bool isConnected;  //信息接收进程 private Thread _ReceiveThread = null; //网络检测进程 private Thread _connectionDetectorThread = null;  private Socket clientSocket = null; private static byte[] result = new byte[1024];  //单例模式 private static nettyClient instance;  public static nettyClient GetInstance() {     if (instance == null)     {         instance = new nettyClient();     }     return instance; }  public static nettyClient GetInstance(string ip,int port) {     if (instance == null)     {         instance = new nettyClient(ip,port);     }     return instance; }  //默认服务器IP地址构造函数 public nettyClient() {     startConnect ();      //初始化网络检测线程     _connectionDetectorThread = new Thread (new ThreadStart (connectionDetector));     //开启网络检测线程[用于检测是否正在连接,否则重新连接]     _connectionDetectorThread.Start ();  }  //自定义服务器IP地址构造函数 public nettyClient(string ip,int port) {     IP = ip;     Port = port;      startConnect ();      //初始化网络检测线程     _connectionDetectorThread = new Thread (new ThreadStart (connectionDetector));     //开启网络检测线程[用于检测是否正在连接,否则重新连接]     _connectionDetectorThread.Start ();  }  private void startConnect() {      //创建Socket对象, 这里我的连接类型是TCP     clientSocket = new Socket (AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);      //服务器IP地址     IPAddress ipAddress = IPAddress.Parse (IP);     //服务器端口     IPEndPoint ipEndpoint = new IPEndPoint (ipAddress, Port);     //这是一个异步的建立连接,当连接建立成功时调用connectCallback方法     IAsyncResult result = clientSocket.BeginConnect (ipEndpoint,new AsyncCallback (connectCallback),clientSocket);     //这里做一个超时的监测,当连接超过5秒还没成功表示超时     bool success = result.AsyncWaitHandle.WaitOne( 5000, true );     if ( !success )     {         //超时         clientSocket.Close();         Debug.Log("connect Time Out");          if (_ReceiveThread != null)                 _ReceiveThread.Abort();     //            Closed();     }else             {         //如果连接成功则开启接受进程,发送信息         if (clientSocket.Connected) {              this.isConnected = true;              //初始化线程             _ReceiveThread = new Thread (new ThreadStart (Receive));             //开启线程[用于接收数据]             _ReceiveThread.Start ();              //发送数据             Send ();         }     }   }  /// <summary> /// 发送数据 /// </summary> public void Send() {     for (int i = 0; i < 2; i++)     {         Thread.Sleep(1000);         //UTF8编码         clientSocket.Send(System.Text.Encoding.UTF8.GetBytes((i+1)+"=> Netty服务端您好/r/n"));     } }  //向服务端发送一条字符串 //一般不会发送字符串 应该是发送数据包 public void SendMessage(string str) {      byte[] msg = System.Text.Encoding.UTF8.GetBytes(str);      if(!clientSocket.Connected)     {         clientSocket.Close();         return;     }     try     {         IAsyncResult asyncSend = clientSocket.BeginSend (msg,0,msg.Length,SocketFlags.None,new AsyncCallback (sendCallback),clientSocket);         bool success = asyncSend.AsyncWaitHandle.WaitOne( 5000, true );          if ( !success )         {             clientSocket.Close();             Debug.Log("Failed to SendMessage server.");         }else              Debug.Log("Message has been sent!");     }     catch     {         Debug.Log("send message error" );     } }  /// <summary> /// 接收数据线程 /// </summary> public void Receive() {     int receiveLength = 0;      try     {         while (true)         {             if(!clientSocket.Connected)             {                 //与服务器断开连接跳出循环                 Debug.Log("Failed to clientSocket server.");                 clientSocket.Close();                 break;             }              try             {                 //Receive方法中会一直等待服务端回发消息                 //如果没有回发会一直在这里等着。                 int i = clientSocket.Receive(result);                 if(i <= 0)                 {                     clientSocket.Close();                      _ReceiveThread.Abort();                      Debug.Log("断开连接");                     break;                 }                  if((receiveLength = clientSocket.Receive(result)) > 0)                 {                     //UTF8解码                     Console.WriteLine("接收服务器消息:{0}", Encoding.UTF8.GetString(result, 0, receiveLength));                     Debug.Log(Encoding.UTF8.GetString(result, 0, receiveLength));                 }             }             catch (Exception ex)             {                 Debug.Log("Failed to clientSocket error." + ex);                 clientSocket.Close();             }         }     }     catch (Exception)     {          throw;     } }  /// <summary> /// 重新连接线程 /// </summary> public void connectionDetector() {     try     {         int connectTime = 0;          while (true)         {             try             {                  if(clientSocket.Connected)                 {                     Debug.Log("网络检测中,连接状态为:" + clientSocket.Connected);                      connectTime    = 0;                 }                 else if(!clientSocket.Connected)                 {                     Debug.Log("网络检测中,连接状态为:False");                      this.isConnected = false;                      //尝试重连                     Debug.Log("正在尝试第"+ connectTime.ToString() +"次重连");                     //连接                     startConnect ();                     //每5秒执行一次重连                     Thread.Sleep(5000);                      connectTime +=1 ;                 }             }             catch (Exception ex)             {                 Debug.Log(ex);             }         }     }     catch (Exception)     {          throw;     } }  static void Main(string[] args) {     new nettyClient(); }  //发送信息-回调 private void sendCallback (IAsyncResult asyncSend) {     Debug.Log (asyncSend.AsyncState); }  //连接-回调 private void connectCallback(IAsyncResult asyncConnect) {  }  //关闭Socket public void Closed() {     try{         if(clientSocket != null && clientSocket.Connected)         {             clientSocket.Shutdown(SocketShutdown.Both);             clientSocket.Close();          }         clientSocket = null;          //关闭线程         _ReceiveThread.Abort ();         _connectionDetectorThread.Abort ();          Debug.Log ("已关闭Socket");     }catch(Exception e) {         throw;     }   } }

三、本地测试


1.连接成功,收发信息正常
Unity客户端与Netty服务器通信搭建(二):Unity客户端程序
Unity控制台

Unity客户端与Netty服务器通信搭建(二):Unity客户端程序
IntelliJ IDEA控制台

2.连接失败,尝试重新连接
Unity客户端与Netty服务器通信搭建(二):Unity客户端程序
失败重连

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Unity客户端与Netty服务器通信搭建(二):Unity客户端程序

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址