465 lines
9.2 KiB
C#
465 lines
9.2 KiB
C#
![]() |
// ***********************************************************************
|
|||
|
// Assembly : Unity
|
|||
|
// Author : Kimch
|
|||
|
// Created : 2019-5-16
|
|||
|
//
|
|||
|
// Last Modified By : Kimch
|
|||
|
// Last Modified On :
|
|||
|
// ***********************************************************************
|
|||
|
// <copyright file= "NetworkProxy" company=""></copyright>
|
|||
|
// <summary></summary>
|
|||
|
// ***********************************************************************
|
|||
|
namespace G
|
|||
|
{
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using F;
|
|||
|
using F.Network;
|
|||
|
using PureMVC.Interfaces;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
public sealed class NetworkProxy : GameProxy
|
|||
|
{
|
|||
|
#region Connector
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
private IConnector _connector;
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
private GameNetworkAdapter _adapter;
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
private readonly Queue<GamePacket> _sendQueue = new Queue<GamePacket>();
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
private bool _connecting;
|
|||
|
/// <summary>
|
|||
|
/// 最大重连次数
|
|||
|
/// </summary>
|
|||
|
private int _maxReconnection = 3;
|
|||
|
/// <summary>
|
|||
|
/// 当前重连次数
|
|||
|
/// </summary>
|
|||
|
private int _curReconnection = -1;
|
|||
|
/// <summary>
|
|||
|
/// 重连时间
|
|||
|
/// </summary>
|
|||
|
private float _reconnectionTimer = 0f;
|
|||
|
/// <summary>
|
|||
|
/// 重连间隔
|
|||
|
/// </summary>
|
|||
|
private float _reconnectionInterval = 2f;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 是否连接
|
|||
|
/// </summary>
|
|||
|
public bool connected
|
|||
|
{
|
|||
|
get;
|
|||
|
private set;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
public string connectURL
|
|||
|
{
|
|||
|
get;
|
|||
|
set;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public void AutoConnect()
|
|||
|
{
|
|||
|
if (_curReconnection == -1)
|
|||
|
{
|
|||
|
_curReconnection = 0;
|
|||
|
Connect();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 不要用对内
|
|||
|
/// </summary>
|
|||
|
public void Connect()
|
|||
|
{
|
|||
|
if (!string.IsNullOrEmpty(connectURL))
|
|||
|
{
|
|||
|
Connect(connectURL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 不要用对内
|
|||
|
/// </summary>
|
|||
|
/// <param name="address">"127.0.0.1:12356"</param>
|
|||
|
public void Connect(string address)
|
|||
|
{
|
|||
|
if (!connected)
|
|||
|
{
|
|||
|
_connecting = true;
|
|||
|
_connector.Connect(address);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Send(GamePacket packet)
|
|||
|
{
|
|||
|
if (connected)
|
|||
|
{
|
|||
|
_connector.Send(packet);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
AutoConnect();
|
|||
|
_sendQueue.Enqueue(packet);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender"></param>
|
|||
|
/// <param name="e"></param>
|
|||
|
private void OnNetworkRecv(object sender, IPacket e)
|
|||
|
{
|
|||
|
if (e is GamePacket packet)
|
|||
|
{
|
|||
|
if (packet.error == GamePacket.ERROR_CODE_OK)
|
|||
|
{
|
|||
|
if (packet.id == 0)
|
|||
|
{
|
|||
|
ProcessPing(packet);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
#if UNITY_EDITOR
|
|||
|
Debug.Log("S2C-----id:" + e.id + "------" + e.data.ToString());
|
|||
|
#endif
|
|||
|
KFramework.GameFacade.Recv(packet);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Debug.Log($"NetWork Error : {packet.error}");
|
|||
|
ProcessError(packet.error);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Debug.Log($"网络包格式错误");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 收到网络错误
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender"></param>
|
|||
|
/// <param name="e"></param>
|
|||
|
private void OnNetworkError(object sender, NetworkErrorEventArgs e)
|
|||
|
{
|
|||
|
switch (e.errorCode)
|
|||
|
{
|
|||
|
case NetworkError.ConnectError:
|
|||
|
case NetworkError.SendError:
|
|||
|
case NetworkError.ReceiveError:
|
|||
|
case NetworkError.SocketError:
|
|||
|
case NetworkError.AddressError:
|
|||
|
_connecting = false;
|
|||
|
connected = false;
|
|||
|
break;
|
|||
|
case NetworkError.SerializeError:
|
|||
|
case NetworkError.DeserializePacketHeaderError:
|
|||
|
case NetworkError.DeserializePacketError:
|
|||
|
_connecting = false;
|
|||
|
connected = false;
|
|||
|
_connector.Close();
|
|||
|
break;
|
|||
|
case NetworkError.CustomError:
|
|||
|
break;
|
|||
|
}
|
|||
|
var errorMessage = $"{e.errorCode} {e.errorMessage} {e.customErrorData}";
|
|||
|
Debug.Log(errorMessage);
|
|||
|
//UI.MessageBox.ShowMessage("网络错误", errorMessage, () =>
|
|||
|
// {
|
|||
|
// });
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender"></param>
|
|||
|
/// <param name="e"></param>
|
|||
|
private void OnNetworkClosed(object sender, NetworkClosedEventArgs e)
|
|||
|
{
|
|||
|
_connecting = false;
|
|||
|
connected = false;
|
|||
|
|
|||
|
UnityEngine.Debug.Log("OnNetworkClosed.");
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender"></param>
|
|||
|
/// <param name="e"></param>
|
|||
|
private void OnNetworkConnected(object sender, NetworkConnectedEventArgs e)
|
|||
|
{
|
|||
|
_connecting = false;
|
|||
|
connected = true;
|
|||
|
UnityEngine.Debug.Log("NetworkConnected.");
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Ping
|
|||
|
|
|||
|
private const float DEFAULT_PING_INTERVAL = 30f;
|
|||
|
|
|||
|
private DateTime _sendPingTime = DateTime.MinValue;
|
|||
|
/// <summary>
|
|||
|
/// 上一次发送过去的时间
|
|||
|
/// </summary>
|
|||
|
public float pingElapseSeconds { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 丢失Ping包
|
|||
|
/// </summary>
|
|||
|
public int lossPingCount { get; set; }
|
|||
|
|
|||
|
private float _pingInterval = DEFAULT_PING_INTERVAL;
|
|||
|
/// <summary>
|
|||
|
/// 获取或设置Ping间隔时长,以秒为单位。
|
|||
|
/// </summary>
|
|||
|
public float pingInterval
|
|||
|
{
|
|||
|
get { return _pingInterval; }
|
|||
|
set { _pingInterval = value; }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 发包延迟(单位秒)
|
|||
|
/// </summary>
|
|||
|
public float lastPing { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 平均延迟(单位秒)
|
|||
|
/// </summary>
|
|||
|
public float averagePing { get; set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
/// <param name="resetPingElapseSeconds"></param>
|
|||
|
public void Reset(bool resetPingElapseSeconds)
|
|||
|
{
|
|||
|
if (resetPingElapseSeconds)
|
|||
|
{
|
|||
|
pingElapseSeconds = 0f;
|
|||
|
}
|
|||
|
lossPingCount = 0;
|
|||
|
}
|
|||
|
|
|||
|
public void SetLastSend()
|
|||
|
{
|
|||
|
_sendPingTime = DateTime.UtcNow;
|
|||
|
}
|
|||
|
|
|||
|
public void SetLastRecv()
|
|||
|
{
|
|||
|
if (_sendPingTime != DateTime.MinValue)
|
|||
|
{
|
|||
|
lastPing = (float)((DateTime.UtcNow - _sendPingTime).TotalSeconds);
|
|||
|
_sendPingTime = DateTime.MinValue;
|
|||
|
averagePing = (averagePing + lastPing) * 0.5f;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public bool SendPing()
|
|||
|
{
|
|||
|
Debug.Log("SendPing");
|
|||
|
Send(new GamePacket
|
|||
|
{
|
|||
|
//id = msg.C2SHeartBeat.MessageType,
|
|||
|
//data = new msg.C2SHeartBeat()
|
|||
|
});
|
|||
|
SetLastSend();
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
public void ProcessPing(GamePacket packet)
|
|||
|
{
|
|||
|
Debug.Log("RecvPing");
|
|||
|
SetLastRecv();
|
|||
|
this.lossPingCount--;
|
|||
|
}
|
|||
|
|
|||
|
private void UpdatePing(float deltaTime)
|
|||
|
{
|
|||
|
if (pingInterval > 0f)
|
|||
|
{
|
|||
|
var needSendPing = false;
|
|||
|
int pingLossCount = 0;
|
|||
|
|
|||
|
pingElapseSeconds += deltaTime;
|
|||
|
if (pingElapseSeconds >= pingInterval)
|
|||
|
{
|
|||
|
needSendPing = true;
|
|||
|
this.lossPingCount++;
|
|||
|
}
|
|||
|
|
|||
|
if (needSendPing && SendPing())
|
|||
|
{
|
|||
|
pingElapseSeconds = 0f;
|
|||
|
|
|||
|
if (pingLossCount > 0)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Error
|
|||
|
|
|||
|
public enum ErrorCode
|
|||
|
{
|
|||
|
PLAYER_NOT_ENOUGH_COIN = 1000, // 金币不够
|
|||
|
PLAYER_NOT_ENOUGH_STONE = 1001, // 钻石不够
|
|||
|
PLAYER_NOT_ENOUGH_YUANSHEN = 1002, // 钻石不够
|
|||
|
PLAYER_NOT_ENOUGH_CURRENCY = 1003, // 没有足够货币
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
/// <param name="error"></param>
|
|||
|
public void ProcessErrorCode(ErrorCode error)
|
|||
|
{
|
|||
|
ProcessError((int)error);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
/// <param name="error"></param>
|
|||
|
public void ProcessError(int error)
|
|||
|
{
|
|||
|
//var errorItem = ItemProxy.Instance.GetStaticItem<ItemError>(error);
|
|||
|
//if (errorItem != null)
|
|||
|
//{
|
|||
|
// switch (errorItem.type)
|
|||
|
// {
|
|||
|
// case 0:
|
|||
|
// break;
|
|||
|
// case 1:
|
|||
|
// break;
|
|||
|
// case 2:
|
|||
|
// break;
|
|||
|
// case 3:
|
|||
|
// break;
|
|||
|
// case 4:
|
|||
|
// break;
|
|||
|
// default:
|
|||
|
// break;
|
|||
|
// }
|
|||
|
//}
|
|||
|
//else
|
|||
|
//{
|
|||
|
//}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Proxy
|
|||
|
|
|||
|
private static NetworkProxy _Instance;
|
|||
|
public static NetworkProxy Instance { get { return _Instance; } }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
public override void Init()
|
|||
|
{
|
|||
|
KFramework.NetworkManager.networkConnected += this.OnNetworkConnected;
|
|||
|
KFramework.NetworkManager.networkClosed += this.OnNetworkClosed;
|
|||
|
KFramework.NetworkManager.networkError += this.OnNetworkError;
|
|||
|
|
|||
|
//_adapter = new GameNetworkAdapter();
|
|||
|
//_connector = KFramework.NetworkManager.CreateConnector("GameConnector", _adapter);
|
|||
|
//_connector.SetDefaultHandler(OnNetworkRecv);
|
|||
|
}
|
|||
|
|
|||
|
static readonly int[] _ListNotificationInterests = new int[] {
|
|||
|
GlobalDefine.EVENT_NETWORK_PACKET,
|
|||
|
};
|
|||
|
|
|||
|
public override IList<int> ListNotificationInterests()
|
|||
|
{
|
|||
|
return _ListNotificationInterests;
|
|||
|
}
|
|||
|
|
|||
|
public override void HandleNotification(INotification notification)
|
|||
|
{
|
|||
|
OnNetworkRecv(notification.Type, notification.Body as IPacket);
|
|||
|
}
|
|||
|
|
|||
|
private void Awake()
|
|||
|
{
|
|||
|
_Instance = this;
|
|||
|
}
|
|||
|
|
|||
|
private void OnDestroy()
|
|||
|
{
|
|||
|
if (_connector != null)
|
|||
|
{
|
|||
|
_connector.Close();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void LateUpdate()
|
|||
|
{
|
|||
|
return;
|
|||
|
if (connected)
|
|||
|
{
|
|||
|
while (connected && _sendQueue.Count > 0)
|
|||
|
{
|
|||
|
_curReconnection = 0;
|
|||
|
Send(_sendQueue.Dequeue());
|
|||
|
}
|
|||
|
UpdatePing(Time.deltaTime);
|
|||
|
}
|
|||
|
else if (!_connecting)
|
|||
|
{
|
|||
|
if (_curReconnection >= 0)
|
|||
|
{
|
|||
|
_reconnectionTimer += Time.deltaTime;
|
|||
|
if (_reconnectionTimer > _reconnectionInterval && _curReconnection < _maxReconnection)
|
|||
|
{
|
|||
|
Connect();
|
|||
|
_curReconnection++;
|
|||
|
_reconnectionTimer = 0;
|
|||
|
if (_curReconnection >= _maxReconnection)
|
|||
|
{
|
|||
|
//UI.MessageBox.ShowMessage("网络连接断开", "请重新连接", () =>
|
|||
|
// {
|
|||
|
// _curReconnection = 0;
|
|||
|
// });
|
|||
|
}
|
|||
|
Debug.Log("自动重连 " + _curReconnection);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
}
|
|||
|
}
|