1. 程式人生 > >Unity使用WebSocket(基於BaseHTTP外掛)

Unity使用WebSocket(基於BaseHTTP外掛)

伺服器:使用c#寫的,用來持續給一個埠發資料

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Threading;

namespace WebSocketServer
{
    class Program
    {
        static string byte_to_string(byte[] b)
        {
            string s = "";
            foreach (byte _b in b)
            {
                s += _b.ToString();
            }
            return s;
        }
        static void Main(string[] args)
        {
            int port = 1818;
            byte[] buffer = new byte[1024];

            IPEndPoint localEP = new IPEndPoint(IPAddress.Any, port);
            Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                listener.Bind(localEP);
                listener.Listen(10);

                Console.WriteLine("等待客戶端連線....");
                Socket sc = listener.Accept();//接受一個連線  
                Console.WriteLine("接受到了客戶端:" + sc.RemoteEndPoint.ToString() + "連線....");

                //握手  
                int length = sc.Receive(buffer);//接受客戶端握手資訊  
                sc.Send(PackHandShakeData(GetSecKeyAccetp(buffer, length)));
                Console.WriteLine("已經發送握手協議了....");

                while (true)
                {
                    Thread.Sleep(1000);
                    //主動傳送資料
                    string lines = "{\"info\":[{\"area\":11,\"x\":80,\"y\":50},{\"area\":5,\"x\":76,\"y\":48}]}";
                    Console.WriteLine("傳送資料:“" + lines + "” 至客戶端....");
                    sc.Send(PackData(lines));
                }

                //接受客戶端資料  
                Console.WriteLine("等待客戶端資料....");
                length = sc.Receive(buffer);//接受客戶端資訊  
                string clientMsg = AnalyticData(buffer, length);
                Console.WriteLine("接受到客戶端資料:" + clientMsg);

                //傳送資料  
                //string sendMsg = "您好," + clientMsg;
                //Console.WriteLine("傳送資料:“" + sendMsg + "” 至客戶端....");
                //sc.Send(PackData(sendMsg));

                Console.WriteLine("演示Over!");
                Console.Read();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

        }

        /// <summary>  
        /// 打包握手資訊  
        /// </summary>  
        /// <param name="secKeyAccept">Sec-WebSocket-Accept</param>  
        /// <returns>資料包</returns>  
        private static byte[] PackHandShakeData(string secKeyAccept)
        {
            var responseBuilder = new StringBuilder();
            responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + Environment.NewLine);
            responseBuilder.Append("Upgrade: websocket" + Environment.NewLine);
            responseBuilder.Append("Connection: Upgrade" + Environment.NewLine);
            responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine + Environment.NewLine);
            return Encoding.UTF8.GetBytes(responseBuilder.ToString());
        }

        /// <summary>  
        /// 生成Sec-WebSocket-Accept  
        /// </summary>  
        /// <param name="handShakeText">客戶端握手資訊</param>  
        /// <returns>Sec-WebSocket-Accept</returns>  
        private static string GetSecKeyAccetp(byte[] handShakeBytes, int bytesLength)
        {
            string handShakeText = Encoding.UTF8.GetString(handShakeBytes, 0, bytesLength);
            string key = string.Empty;
            Regex r = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n");
            Match m = r.Match(handShakeText);
            if (m.Groups.Count != 0)
            {
                key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n", "$1").Trim();
            }
            byte[] encryptionString = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
            return Convert.ToBase64String(encryptionString);
        }

        /// <summary>  
        /// 解析客戶端資料包  
        /// </summary>  
        /// <param name="recBytes">伺服器接收的資料包</param>  
        /// <param name="recByteLength">有效資料長度</param>  
        /// <returns></returns>  
        private static string AnalyticData(byte[] recBytes, int recByteLength)
        {
            if (recByteLength < 2) { return string.Empty; }

            bool fin = (recBytes[0] & 0x80) == 0x80; // 1bit,1表示最後一幀    
            if (!fin)
            {
                return string.Empty;// 超過一幀暫不處理   
            }

            bool mask_flag = (recBytes[1] & 0x80) == 0x80; // 是否包含掩碼    
            if (!mask_flag)
            {
                return string.Empty;// 不包含掩碼的暫不處理  
            }

            int payload_len = recBytes[1] & 0x7F; // 資料長度    

            byte[] masks = new byte[4];
            byte[] payload_data;

            if (payload_len == 126)
            {
                Array.Copy(recBytes, 4, masks, 0, 4);
                payload_len = (UInt16)(recBytes[2] << 8 | recBytes[3]);
                payload_data = new byte[payload_len];
                Array.Copy(recBytes, 8, payload_data, 0, payload_len);

            }
            else if (payload_len == 127)
            {
                Array.Copy(recBytes, 10, masks, 0, 4);
                byte[] uInt64Bytes = new byte[8];
                for (int i = 0; i < 8; i++)
                {
                    uInt64Bytes[i] = recBytes[9 - i];
                }
                UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);

                payload_data = new byte[len];
                for (UInt64 i = 0; i < len; i++)
                {
                    payload_data[i] = recBytes[i + 14];
                }
            }
            else
            {
                Array.Copy(recBytes, 2, masks, 0, 4);
                payload_data = new byte[payload_len];
                Array.Copy(recBytes, 6, payload_data, 0, payload_len);

            }

            for (var i = 0; i < payload_len; i++)
            {
                payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]);
            }

            return Encoding.UTF8.GetString(payload_data);
        }


        /// <summary>  
        /// 打包伺服器資料  
        /// </summary>  
        /// <param name="message">資料</param>  
        /// <returns>資料包</returns>  
        private static byte[] PackData(string message)
        {
            byte[] contentBytes = null;
            byte[] temp = Encoding.UTF8.GetBytes(message);

            if (temp.Length < 126)
            {
                contentBytes = new byte[temp.Length + 2];
                contentBytes[0] = 0x81;
                contentBytes[1] = (byte)temp.Length;
                Array.Copy(temp, 0, contentBytes, 2, temp.Length);
            }
            else if (temp.Length < 0xFFFF)
            {
                contentBytes = new byte[temp.Length + 4];
                contentBytes[0] = 0x81;
                contentBytes[1] = 126;
                contentBytes[2] = (byte)(temp.Length & 0xFF);
                contentBytes[3] = (byte)(temp.Length >> 8 & 0xFF);
                Array.Copy(temp, 0, contentBytes, 4, temp.Length);
            }
            else
            {
                // 暫不處理超長內容    
            }

            return contentBytes;
        }

    }
}
客戶端:

這個是用來進行資料的接收

using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using BestHTTP;
using BestHTTP.WebSocket;

public class WabData
{
    /// <summary>  
    /// The WebSocket address to connect  
    /// </summary>  
    private readonly string address = "ws://192.168.199.208:1818";

    /// <summary>  
    /// Default text to send  
    /// </summary>  
    private string _msgToSend = "Hello World!";

    /// <summary>  
    /// Debug text to draw on the gui  
    /// </summary>  
    private string _text = string.Empty;

    /// <summary>  
    /// Saved WebSocket instance  
    /// </summary>  
    private WebSocket _webSocket;

    private Queue<DataInfo> _msgQueue = new Queue<DataInfo>();

    public Queue<DataInfo> MsgQueue { get { return _msgQueue; } } 
    public WebSocket WebSocket { get { return _webSocket; } }
    public string Address { get { return address; } }
    public string Text { get { return _text; } }

    public string MsgToSend
    {
        get { return _msgToSend; }
        set
        {
            _msgToSend = value;
            SendMsg(value);
        }
    }

    public void OpenWebSocket()
    {
        if (_webSocket == null)
        {
            // Create the WebSocket instance  
            _webSocket = new WebSocket(new Uri(address));

            if (HTTPManager.Proxy != null)
                _webSocket.InternalRequest.Proxy = new HTTPProxy(HTTPManager.Proxy.Address, HTTPManager.Proxy.Credentials, false);

            // Subscribe to the WS events  
            _webSocket.OnOpen += OnOpen;
            _webSocket.OnMessage += OnMessageReceived;
            _webSocket.OnClosed += OnClosed;
            _webSocket.OnError += OnError;

            // Start connecting to the server  
            _webSocket.Open();
        }
    }

    public void SendMsg(string msg)
    {
        // Send message to the server  
        _webSocket.Send(msg);
    }

    public void CloseSocket()
    {
        // Close the connection  
        _webSocket.Close(1000, "Bye!");
    }

    /// <summary>  
    /// Called when the web socket is open, and we are ready to send and receive data  
    /// </summary>  
    void OnOpen(WebSocket ws)
    {
        Debug.Log("-WebSocket Open!\n");
    }

    /// <summary>  
    /// Called when we received a text message from the server  
    /// </summary>  
    void OnMessageReceived(WebSocket ws, string message)
    {
        DataInfo datainfo = JsonUtility.FromJson<DataInfo>(message);
        if (datainfo != null) _msgQueue.Enqueue(datainfo);
    }

    /// <summary>  
    /// Called when the web socket closed  
    /// </summary>  
    void OnClosed(WebSocket ws, UInt16 code, string message)
    {
        Debug.Log(string.Format("-WebSocket closed! Code: {0} Message: {1}\n", code, message));
        _webSocket = null;
    }

    /// <summary>  
    /// Called when an error occured on client side  
    /// </summary>  
    void OnError(WebSocket ws, Exception ex)
    {
        string errorMsg = string.Empty;
        if (ws.InternalRequest.Response != null)
            errorMsg = string.Format("Status Code from Server: {0} and Message: {1}", ws.InternalRequest.Response.StatusCode, ws.InternalRequest.Response.Message);

        Debug.Log(string.Format("-An error occured: {0}\n",ex != null ? ex.Message : "Unknown Error " + errorMsg));
        _webSocket = null;
    }
}

//{"info":[{"area":11,"x":80,"y":50},{"area":5,"x":76,"y":48}]}
[System.Serializable]
public class DataInfo
{
    public Data[] info;
}

[System.Serializable]
public class Data
{
    public int area;
    public int x;
    public int y;
}
這個是用來獲得上面儲存的資料:
using System;
using UnityEngine;
using BestHTTP;
using BestHTTP.WebSocket;  

public class WebSocketSimpet : MonoBehaviour {

    #region Private Fields

    /// <summary>  
    /// The WebSocket address to connect  
    /// </summary>  
    string _address;  

    /// <summary>  
    /// Default text to send  
    /// </summary>  
    string _msgToSend;

    /// <summary>  
    /// Debug text to draw on the gui  
    /// </summary>  
    string _text;

    /// <summary>  
    /// GUI scroll position  
    /// </summary>  
    Vector2 _scrollPos;

    private WabData _wabData;

    #endregion

    #region Unity Events

    void Start()
    {
        _wabData = new WabData();
        _address = _wabData.Address;
        _msgToSend = _wabData.MsgToSend;
        _text = _wabData.Text;
    }

    void Update()
    {
        if (_wabData.MsgQueue.Count > 0)
        {
            DataInfo info = _wabData.MsgQueue.Dequeue();
            string json = JsonUtility.ToJson(info);
            Debug.Log(json);
        }
    }

    void OnDestroy()
    {
        if (_wabData.WebSocket != null)
            _wabData.WebSocket.Close();
    }

    void OnGUI()
    {
        _address = GUILayout.TextField(_address);

        if (_wabData.WebSocket == null && GUILayout.Button("Open Web Socket"))
        {
            _wabData.OpenWebSocket();

            _text += "Opening Web Socket...\n";
        }

        if (_wabData.WebSocket != null && _wabData.WebSocket.IsOpen)
        {
            if (GUILayout.Button("Send", GUILayout.MaxWidth(70)))
            {
                _text += "Sending message...\n";

                // Send message to the server  
                _wabData.WebSocket.Send(_msgToSend);
            }

            if (GUILayout.Button("Close"))
            {
                // Close the connection  
                _wabData.WebSocket.Close(1000, "Bye!");
            }
        }
    }

    #endregion
}


外掛地址:http://download.csdn.net/download/agroupofruffian/10192849