美文网首页Unity学习小组Java&Spring基础技术Unity教程合集
Unity客户端与Netty服务器通信搭建(二):Unity客户

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

作者: LiGoEX | 来源:发表于2016-09-23 10:48 被阅读1314次

    前言

    最近和几个同学一起做一个手游项目,虽然是单机,但是有检测新版本的需求,因此还是要搭建一个服务器来实现客户端检测更新的功能。在朋友的推荐下,我选择使用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工程
    工程截图.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控制台 IntelliJ IDEA控制台
    2.连接失败,尝试重新连接
    失败重连

    相关文章

      网友评论

        本文标题:Unity客户端与Netty服务器通信搭建(二):Unity客户

        本文链接:https://www.haomeiwen.com/subject/gljtyttx.html