using UnityEngine;
using System.Net.Sockets;
using System;
using System.Linq;
using System.IO;
using XFramework.NetOuter;
using UnityEngine.Events;
using System.Collections.Generic;
public class TcpClient {
ProtocolBase protocol=new ProtocolByte();
string path="";
// public string serverMess="";
public Socket socket;
public const int bufferSize=16384;//最大可缓存16kb 的数据
int bufferCount = 0;
byte[] readBuffer = new byte[bufferSize];
byte[] lenbytes=new byte[sizeof(Int32)];
Int32 msgLength;
//string GetConnState;
private MsgDistribution msgDis = new MsgDistribution();
string address="";
int port=0;
float timer;
float heatBeatTime=5;
///
/// 连接状态变化
///
event UnityAction ConnectChanged;
Queue changedQueue = new Queue();//记录支线程 网络状态变化
public TcpClient(UnityAction ConnectChanged = null)
{
this.ConnectChanged += ConnectChanged;
ReadConfig();
AddListener();
ConnectServer();
}
// Mono类代为调用
public void ExtractingMsg()
{
msgDis.Distribution();
timer += Time.deltaTime;
if (timer > heatBeatTime)
{
HeatBeat();
timer = 0;
}
if (changedQueue.Count > 0)
{
ConnectChanged?.Invoke(changedQueue.Dequeue());
}
}
//连接到服务器
private void ConnectServer()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.BeginConnect(address, port, ReceiveConn, null);
//Debug.Log($"尝试建立连接{address}:{port}");
}
private void ReceiveConn(IAsyncResult ar)
{
if (socket.Connected)
{
socket.BeginReceive(readBuffer, 0, bufferSize, SocketFlags.None, ReceiveCb, null);
changedQueue.Enqueue(true);
}
}
//读取配置文件获取IP和端口
private void ReadConfig()
{
path = Application.streamingAssetsPath + "/TcpConfig/ServerAdress.txt";
if (File.Exists(path))
{
string[] config = File.ReadAllText(path, System.Text.Encoding.UTF8).Split(',');
if (config.Length >= 2)
{
address = config[0].Trim();
port = int.Parse(config[1].Trim());
}
else
{
Debug.Log("config is error");
}
}
}
//添加监听消息事件
void AddListener()
{
msgDis.AddListener(NetMsgName.LoginResult.ToString(), new TCPLoginResultExcute());
msgDis.AddListener(NetMsgName.Subject.ToString(), new TCPSubExcute());
msgDis.AddListener(NetMsgName.AdjustingToStu.ToString(), new TCPAdjustingToStuExcute());
msgDis.AddListener(NetMsgName.AddOrRmoveTufa.ToString(), new TCPAddOrRmoveTufaExcute());
msgDis.AddListener(NetMsgName.AppraiseResult.ToString(), new TCPAppraiseResultExcute());
msgDis.AddListener(NetMsgName.GroupUserBreak.ToString(), new UserDiscExcute());//掉线处理逻辑
}
//接收信息的回调
private void ReceiveCb(IAsyncResult ar)
{
try
{
int count = socket.EndReceive(ar);
bufferCount += count;
ProcessData();
socket.BeginReceive(readBuffer, bufferCount, bufferSize- bufferCount, SocketFlags.None, ReceiveCb, null);
}
catch (Exception e)
{
Debug.Log(e.Message+"接收消息失败,断开连接");
changedQueue.Enqueue(false);
socket.Close();
}
}
//验证信息完整程度并删除处理完成的信息
private void ProcessData()
{
if (bufferCount < sizeof(Int32))
return;
Array.Copy(readBuffer,lenbytes,sizeof(Int32));
msgLength = BitConverter.ToInt32(lenbytes,0);
if (msgLength < 0)
{
Debug.Log("ReadBuffer解析数据长度解析有误");
return;
}
if (msgLength > bufferSize)
{
Debug.Log("ReadBuffer数据长度超出缓存空间");
return;
}
if (bufferCount < sizeof(Int32) + msgLength)
return;
ProtocolByte proto = (ProtocolByte)protocol.Decode(readBuffer, sizeof(Int32), msgLength);
//HandleMsg(proto);
ExcuteParam excute = new ExcuteParam(address,proto.GetProtocolName(), proto);
msgDis.Enqueue(excute);
int count = bufferCount - sizeof(Int32) - msgLength;
Array.Copy(readBuffer,sizeof(Int32)+msgLength,readBuffer,0,count);
bufferCount = count;
if (bufferCount > 0)
ProcessData();
}
//发送位置信息
//发送传输协议到服务器
public void Send(ProtocolBase proto)
{
byte[] bytes = proto.Encode();
byte[] length = BitConverter.GetBytes(bytes.Length);
byte[] sendBytes = length.Concat(bytes).ToArray();
try
{
socket.Send(sendBytes);
}
catch (Exception)
{
//Debug.Log("接收消息失败,断开连接");
socket.Close();
}
}
//心跳
void HeatBeat()
{
//Debug.Log(connIsRight);
if (socket.Connected)
{
ProtocolByte protoco = new ProtocolByte();
protoco.AddString("HeatBeat");
Send(protoco);
}
else
{
ConnectServer();
}
}
//关闭连接
public bool Close()
{
try
{
socket.Close();
ConnectChanged?.Invoke(false);
return true;
}
catch (Exception e)
{
Debug.Log("关闭失败:"+e.Message);
return false;
}
}
}