You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
8.4 KiB
283 lines
8.4 KiB
using System.Collections; |
|
using System.Collections.Generic; |
|
using UnityEngine; |
|
using UnityEngine.Events; |
|
using QFramework; |
|
using System; |
|
|
|
namespace TCPClientTools |
|
{ |
|
public class TCPMangerArchitecture : Architecture<TCPMangerArchitecture> |
|
{ |
|
protected override void Init() |
|
{ |
|
this.RegisterUtility(new TCPUtility()); |
|
this.RegisterModel(new TCPEventModel()); |
|
} |
|
} |
|
//统筹管理TCP的命令池以及相关链接信息 |
|
public class TCPEventModel : AbstractModel, ICanSendCommand,ICanRegisterEvent |
|
{ |
|
public IOCContainer mCommandContainer = new IOCContainer(); |
|
public UnityStringEvent onTCPRecived = new UnityStringEvent(); |
|
private TCPLinkState tcpState = TCPLinkState.NoIp; |
|
private string tcpAddress = ""; |
|
private int tcpPort = 0; |
|
public string myAddress = ""; |
|
|
|
protected override void OnInit() |
|
{ |
|
myAddress = this.GetUtility<TCPUtility>().GetIP(); |
|
this.RegisterEvent<onLinkException>(e=> { |
|
setTCPState(TCPLinkState.LinkTimeOut); |
|
this.GetUtility<TCPUtility>().CloseTCPClient(); |
|
}); |
|
} |
|
|
|
public void sendResponseCommand<T>(string json) where T : ITCPResponse,new() { |
|
if (mCommandContainer.Get<ExcuteResponseCommand<T>>()==null) { |
|
mCommandContainer.Register(new ExcuteResponseCommand<T>(new T())); |
|
} |
|
mCommandContainer.Get<ExcuteResponseCommand<T>>().setJson(json); |
|
this.SendCommand(mCommandContainer.Get<ExcuteResponseCommand<T>>()); |
|
} |
|
/// <summary> |
|
/// 开启接收指定数据 |
|
/// </summary> |
|
/// <typeparam name="T">数据格式类型</typeparam> |
|
public void onReceive<T>() where T : ITCPResponse, new() |
|
{ |
|
onTCPRecived.AddListener(sendResponseCommand<T>); |
|
} |
|
/// <summary> |
|
/// 关闭接收指定数据 |
|
/// </summary> |
|
/// <typeparam name="T">数据格式类型</typeparam> |
|
public void offReceive<T>() where T : ITCPResponse, new() |
|
{ |
|
onTCPRecived.RemoveListener(sendResponseCommand<T>); |
|
} |
|
|
|
/// <summary> |
|
/// 发送数据 |
|
/// </summary> |
|
/// <typeparam name="T">数据类型</typeparam> |
|
/// <param name="request">请求数据</param> |
|
public void sendRequestCommand<T>(T request)where T : ITCPRequest |
|
{ |
|
if (mCommandContainer.Get<SendRequestCommand<T>>() == null) { |
|
mCommandContainer.Register(new SendRequestCommand<T>(request)); |
|
} |
|
mCommandContainer.Get<SendRequestCommand<T>>().setRequest(request); |
|
this.SendCommand(mCommandContainer.Get<SendRequestCommand<T>>()); |
|
} |
|
|
|
|
|
public void setTCPState(TCPLinkState state) { |
|
this.tcpState = state; |
|
this.SendEvent(new TCPStateChangedEvent(state)); |
|
} |
|
public TCPLinkState getState() { |
|
return this.tcpState; |
|
} |
|
|
|
/// <summary> |
|
/// 设置对应IP,设置完毕后,自动进入链接状态(此时需要用户手动监听是否要进行链接服务器) |
|
/// </summary> |
|
/// <param name="ip">ip地址</param> |
|
/// <param name="port">端口号</param> |
|
public void setIP(string ip,int port) { |
|
this.tcpAddress = ip; |
|
this.tcpPort = port; |
|
//此处可以加ip校验 |
|
Debug.LogWarning("此处未进行ip以及端口号校验,日后有需求可以增加"); |
|
setTCPState(TCPLinkState.Linking); |
|
} |
|
|
|
/// <summary> |
|
/// 与服务端建立链接 |
|
/// </summary> |
|
public void linkServer() { |
|
if (tcpState == TCPLinkState.Linking) |
|
{ |
|
if (!this.GetUtility<TCPUtility>().isOpenTCP) { |
|
|
|
bool isSuccess = this.GetUtility<TCPUtility>().StartTCPClient(tcpAddress, tcpPort); |
|
if (isSuccess) { |
|
setTCPState(TCPLinkState.LinkSucess); |
|
} |
|
else |
|
{ |
|
setTCPState(TCPLinkState.LinkFaild); |
|
} |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 与服务端断开链接 |
|
/// </summary> |
|
public void closeServer() |
|
{ |
|
if (tcpState == TCPLinkState.LinkSucess) |
|
{ |
|
if (this.GetUtility<TCPUtility>().isOpenTCP) |
|
{ |
|
|
|
this.GetUtility<TCPUtility>().CloseTCPClient(); |
|
setTCPState(TCPLinkState.NoIp); |
|
} |
|
} |
|
} |
|
} |
|
|
|
#region Command |
|
/// <summary> |
|
/// 处理响应数据,添加对应的Command进行处理,需要提前生成命令池 |
|
/// </summary> |
|
/// <typeparam name="TResponse">响应数据格式</typeparam> |
|
public class ExcuteResponseCommand<TResponse> : AbstractCommand where TResponse : ITCPResponse |
|
{ |
|
public string json; |
|
private TResponse response; |
|
public ExcuteResponseCommand(TResponse response) |
|
{ |
|
if (this.response == null) |
|
{ |
|
this.response = response; |
|
} |
|
} |
|
protected override void OnExecute() |
|
{ |
|
bool isSet = response.trySetData(json); |
|
if (isSet) |
|
{ |
|
Debug.Log("Received:" + response.toJson() + response.GetType()); |
|
this.SendEvent(new ResponseMsgEvent(response)); |
|
} |
|
} |
|
public void setJson(string json) |
|
{ |
|
this.json = json; |
|
} |
|
} |
|
|
|
public class SendRequestCommand<TRequest> : AbstractCommand where TRequest : ITCPRequest |
|
{ |
|
public TRequest request; |
|
public SendRequestCommand(TRequest request) |
|
{ |
|
this.request = request; |
|
} |
|
protected override void OnExecute() |
|
{ |
|
if (this.GetUtility<TCPUtility>().isOpenTCP) |
|
{ |
|
this.GetUtility<TCPUtility>().sendData(request.toJson()); |
|
} |
|
else |
|
{ |
|
Debug.LogWarning("请先开启TCP链接"); |
|
} |
|
//throw new NotImplementedException(); |
|
} |
|
public void setRequest(TRequest request) |
|
{ |
|
this.request = request; |
|
} |
|
} |
|
#endregion |
|
|
|
#region interface |
|
public interface ITCPResponse |
|
{ |
|
string toJson(); |
|
/// <summary> |
|
/// 尝试填充数据,如果json不合法,则返回false,忽略该条数据响应 |
|
/// </summary> |
|
/// <param name="json"></param> |
|
/// <returns></returns> |
|
bool trySetData(string json); |
|
string getException(); |
|
} |
|
|
|
public interface ITCPRequest |
|
{ |
|
string toJson(); |
|
} |
|
#endregion |
|
|
|
#region AbstractClass |
|
/// <summary> |
|
/// 使用抽象类时,必须满足可序列化 |
|
/// </summary> |
|
[Serializable] |
|
public abstract class AbstractTCPResponse:ITCPResponse |
|
{ |
|
private string exceptionMsg; |
|
public virtual string toJson() |
|
{ |
|
return JsonUtility.ToJson(this,true); |
|
} |
|
public virtual bool trySetData(string json) |
|
{ |
|
try { |
|
JsonUtility.FromJsonOverwrite(json, this); |
|
return true; |
|
} |
|
catch (Exception e) { |
|
exceptionMsg = e.ToString(); |
|
return false; |
|
} |
|
} |
|
public string getException() |
|
{ |
|
return exceptionMsg; |
|
} |
|
} |
|
#endregion |
|
|
|
#region enum |
|
public enum TCPLinkState |
|
{ |
|
NoIp = 0, |
|
Linking = 1, |
|
LinkFaild = 2, |
|
LinkSucess = 3, |
|
LinkTimeOut = 4 |
|
} |
|
#endregion |
|
|
|
#region event |
|
public struct ResponseMsgEvent |
|
{ |
|
public ITCPResponse res; |
|
public ResponseMsgEvent(ITCPResponse res_) |
|
{ |
|
res = res_; |
|
} |
|
}; |
|
public struct TCPStateChangedEvent |
|
{ |
|
public TCPLinkState state; |
|
public TCPStateChangedEvent(TCPLinkState state_) |
|
{ |
|
state = state_; |
|
} |
|
} |
|
public struct onLinkException |
|
{ |
|
public string exceptionMsg; |
|
public onLinkException(string exceptionMsg_) |
|
{ |
|
exceptionMsg = exceptionMsg_; |
|
} |
|
} |
|
#endregion |
|
|
|
[Serializable] |
|
public class UnityStringEvent : UnityEvent<string> |
|
{ |
|
|
|
} |
|
} |