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
3 years ago
|
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>
|
||
|
{
|
||
|
|
||
|
}
|
||
|
}
|