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
|
||
}
|
||
}
|