using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using UnityEngine.UI;
using System;
using System.Text;
[XLua.LuaCallCSharp]
public class NetMgr : MonoBehaviour
{
private EvtDefine.ConnSuccessHandle OnConnSuccessHandle;
private EvtDefine.ConnFailedHandle OnConnFailedHandle;
private EvtDefine.ConnCloseHandle OnConnCloseHandle;
private EvtDefine.RecvHandle OnRecvHandle;
private EvtDefine.SocketErrorHandle OnSocketErrorHandle;
private Socket client;
private IPEndPoint address;
private bool isAutoConn = true; //是否开启自动重连接
private bool isHeart = true; //开启心跳
private int reConnCount = 0; //重连次数
private int curConnCount = 0; //当前连接次数
/// <summary>
/// 是否已连接
/// </summary>
public bool isConn
{
get
{
if (client == null)
return false;
return client.Connected;
}
}
/// <summary>
/// 连接
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
/// <param name="rCC">重连次数</param>
public void Connect(string ip, int port, int rCC,
Action connSuccessAcion,
Action<string> connFailedHandle,
Action<string> connCloseHandle,
Action<int, string> recvHandle,
Action<int, string> socketErrorHandle)
{
IPAddress ipAddress = IPAddress.Parse(ip);
address = new IPEndPoint(ipAddress, port);
reConnCount = rCC;
curConnCount = 0;
if (connSuccessAcion != null)
OnConnSuccessHandle = new EvtDefine.ConnSuccessHandle(connSuccessAcion);
if (connFailedHandle != null)
OnConnFailedHandle = new EvtDefine.ConnFailedHandle(connFailedHandle);
if (connCloseHandle != null)
OnConnCloseHandle = new EvtDefine.ConnCloseHandle(connCloseHandle);
if (recvHandle != null)
OnRecvHandle = new EvtDefine.RecvHandle(recvHandle);
if (socketErrorHandle != null)
OnSocketErrorHandle = new EvtDefine.SocketErrorHandle(socketErrorHandle);
StartCoroutine(AutoConn());
StartCoroutine(HeartEnumerator());
}
#region 事件回调
/// <summary>
/// 接收回调
/// </summary>
/// <param name="msgType"></param>
/// <param name="msg"></param>
public void CallRecv(int msgType, string msg)
{
if (OnRecvHandle != null)
{
OnRecvHandle(msgType, msg);
}
}
/// <summary>
/// 异常回调
/// </summary>
/// <param name="msgType"></param>
/// <param name="err"></param>
public void CallSocketError(int msgType, string err)
{
if (OnSocketErrorHandle != null)
{
OnSocketErrorHandle(msgType, err);
}
}
/// <summary>
/// 断线
/// </summary>
/// <param name="msg"></param>
public void CallConnClose(string msg)
{
if (OnConnCloseHandle != null)
{
OnConnCloseHandle(msg);
}
}
//连接成功
private void CallConnSuccess()
{
if (OnConnSuccessHandle != null)
{
OnConnSuccessHandle();
}
}
//连接失败
private void CallConnFailed(Exception ex)
{
if (OnConnFailedHandle != null)
{
OnConnFailedHandle(ex.Message);
}
}
#endregion
/// <summary>
/// 发送心跳
/// </summary>
/// <returns></returns>
private IEnumerator HeartEnumerator()
{
while (isHeart && isConn)
{
Send(1, "heart");
yield return new WaitForSeconds(50);
}
}
/// <summary>
/// 自动重连
/// </summary>
/// <returns></returns>
private IEnumerator AutoConn()
{
while (isAutoConn)
{
if (isConn == false && curConnCount <= reConnCount)
{
//Tools.ShowTip("正在连接...",false);
Connection();
curConnCount++;
}
yield return new WaitForSeconds(1);
}
}
/// <summary>
/// 连接
/// </summary>
/// <returns></returns>
private void Connection()
{
try
{
if (isConn == false)
{
if (address == null)
{
Debug.LogError("网络未初始化");
return;
}
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(address);
//重置连接次数
curConnCount = 0;
CallConnSuccess();
ReceiveDataHandle recv = new ReceiveDataHandle(client);
recv.client.BeginReceive(recv.Bytes, recv.StartPos, recv.EndPos, SocketFlags.None, ReceiveCallback, recv);
}
}
catch (Exception ex)
{
CallConnFailed(ex);
}
}
private void Send(byte[] _bytes)
{
if (client == null || client.Connected == false)
{
Debug.Log("未连接");
//Tools.ShowTip("未连接");
return;
}
client.BeginSend(_bytes, 0, _bytes.Length, SocketFlags.None, SendCallback, null);
}
private void SendCallback(IAsyncResult ar)
{
try
{
client.EndSend(ar);
}
catch (Exception ex)
{
Debug.LogError(string.Format("发送消息失败:{0}", ex.Message));
}
}
public void Send(int cmd, string str)
{
int headerLen = ReceiveDataHandle.HeadLength;
//包内容
byte[] byteContent = Encoding.UTF8.GetBytes(str);
int contentLen = byteContent.Length;
//报文长度
byte[] header = new byte[headerLen];
ushort len = (ushort)(contentLen);
header = BitConverter.GetBytes(len);
byte[] msgType = new byte[headerLen];
msgType = BitConverter.GetBytes((ushort)cmd);
//消息包
byte[] msgPacket = new byte[len + headerLen + headerLen];
header.CopyTo(msgPacket, 0);
msgType.CopyTo(msgPacket, 2);
byteContent.CopyTo(msgPacket, 4);
//发送
Send(msgPacket);
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
ReceiveDataHandle recv = (ReceiveDataHandle)ar.AsyncState;
int recvCount = recv.client.EndReceive(ar);
if (recvCount < ReceiveDataHandle.HeadLength + ReceiveDataHandle.MsgType) //不够解析包头和协议类型
{
//断开客户端
recv.CloseConn();
CallConnClose(string.Empty);
Debug.Log(string.Format("连接已断开"));
return;
}
recv.recvDataLen = recvCount;
ProcessData(recv);
}
catch (Exception ex)
{
CallSocketError(1, ex.Message);
}
}
private void ProcessData(ReceiveDataHandle recv)
{
try
{
//获取报文长度
int bodySize = recv.GetMsgLen();
if (bodySize < 0) //不合法数据
{
//断开客户端
//recv.client.Close();
recv.CloseConn();
CallConnClose(string.Empty);
return;
}
//获取应该要收到的字节
int packLen = bodySize + ReceiveDataHandle.HeadLength + ReceiveDataHandle.MsgType - recv.CurBufferSize;
if (recv.recvDataLen == packLen)
{
//完整包
string msg = System.Text.Encoding.UTF8.GetString(recv.Bytes, 4, bodySize);
CallRecv(recv.GetMsgType(), msg);
Debug.Log(string.Format("收到消息:{0}", msg));
recv.InitBuffer();
recv.client.BeginReceive(recv.Bytes, recv.StartPos, recv.EndPos, SocketFlags.None, new AsyncCallback(ReceiveCallback), recv);
}
else
{
if (recv.recvDataLen < packLen)
{
Debug.Log("不够继续接收");
//不够
recv.CurBufferSize += recv.recvDataLen;
recv.StartPos += recv.recvDataLen;
//继续接收
recv.client.BeginReceive(recv.Bytes, recv.StartPos, ReceiveDataHandle.BufferMaxSize - recv.CurBufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), recv);
}
else if (recv.recvDataLen > packLen)
{
Debug.Log("多余的包,分包");
//完整包
string msg = System.Text.Encoding.UTF8.GetString(recv.Bytes, 4, bodySize);
CallRecv(recv.GetMsgType(), msg);
Debug.Log(string.Format("收到消息:{0}", msg));
//多余的字节
int temp2 = recv.recvDataLen - packLen;
byte[] tempByte = new byte[ReceiveDataHandle.BufferMaxSize];
Array.Copy(recv.Bytes, packLen, tempByte, 0, temp2);
recv.Bytes = tempByte;
recv.recvDataLen = temp2;
if (temp2 < ReceiveDataHandle.HeadLength + ReceiveDataHandle.MsgType)
{
//继续接收
recv.CurBufferSize = temp2;
recv.StartPos = temp2;
recv.client.BeginReceive(recv.Bytes, recv.StartPos, ReceiveDataHandle.BufferMaxSize - recv.CurBufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), recv);
return;
}
ProcessData(recv);
}
}
}
catch (Exception ex)
{
//断开客户端
recv.CloseConn();
CallConnClose(string.Empty);
Debug.LogError(string.Format("连接已断开,处理服务端数据,出现异常", ex.Message));
return;
}
}
/// <summary>
/// 关闭连接
/// </summary>
private void DisConnection()
{
isAutoConn = false;
StopCoroutine(AutoConn());
if (client == null || !client.Connected)
{
return;
}
client.Shutdown(SocketShutdown.Both);
client.Close();
Debug.Log("连接已挂断");
}
private void OnDestroy()
{
OnConnSuccessHandle = null;
OnConnFailedHandle = null;
OnConnCloseHandle = null;
OnRecvHandle = null;
OnSocketErrorHandle = null;
DisConnection();
}
}
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using UnityEngine.UI;
using System;
using System.Text;
[XLua.LuaCallCSharp]
public class NetMgr : MonoBehaviour
{
private EvtDefine.ConnSuccessHandle OnConnSuccessHandle;
private EvtDefine.ConnFailedHandle OnConnFailedHandle;
private EvtDefine.ConnCloseHandle OnConnCloseHandle;
private EvtDefine.RecvHandle OnRecvHandle;
private EvtDefine.SocketErrorHandle OnSocketErrorHandle;
private Socket client;
private IPEndPoint address;
private bool isAutoConn = true; //是否开启自动重连接
private bool isHeart = true; //开启心跳
private int reConnCount = 0; //重连次数
private int curConnCount = 0; //当前连接次数
/// <summary>
/// 是否已连接
/// </summary>
public bool isConn
{
get
{
if (client == null)
return false;
return client.Connected;
}
}
/// <summary>
/// 连接
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
/// <param name="rCC">重连次数</param>
public void Connect(string ip, int port, int rCC,
Action connSuccessAcion,
Action<string> connFailedHandle,
Action<string> connCloseHandle,
Action<int, string> recvHandle,
Action<int, string> socketErrorHandle)
{
IPAddress ipAddress = IPAddress.Parse(ip);
address = new IPEndPoint(ipAddress, port);
reConnCount = rCC;
curConnCount = 0;
if (connSuccessAcion != null)
OnConnSuccessHandle = new EvtDefine.ConnSuccessHandle(connSuccessAcion);
if (connFailedHandle != null)
OnConnFailedHandle = new EvtDefine.ConnFailedHandle(connFailedHandle);
if (connCloseHandle != null)
OnConnCloseHandle = new EvtDefine.ConnCloseHandle(connCloseHandle);
if (recvHandle != null)
OnRecvHandle = new EvtDefine.RecvHandle(recvHandle);
if (socketErrorHandle != null)
OnSocketErrorHandle = new EvtDefine.SocketErrorHandle(socketErrorHandle);
StartCoroutine(AutoConn());
StartCoroutine(HeartEnumerator());
}
#region 事件回调
/// <summary>
/// 接收回调
/// </summary>
/// <param name="msgType"></param>
/// <param name="msg"></param>
public void CallRecv(int msgType, string msg)
{
if (OnRecvHandle != null)
{
OnRecvHandle(msgType, msg);
}
}
/// <summary>
/// 异常回调
/// </summary>
/// <param name="msgType"></param>
/// <param name="err"></param>
public void CallSocketError(int msgType, string err)
{
if (OnSocketErrorHandle != null)
{
OnSocketErrorHandle(msgType, err);
}
}
/// <summary>
/// 断线
/// </summary>
/// <param name="msg"></param>
public void CallConnClose(string msg)
{
if (OnConnCloseHandle != null)
{
OnConnCloseHandle(msg);
}
}
//连接成功
private void CallConnSuccess()
{
if (OnConnSuccessHandle != null)
{
OnConnSuccessHandle();
}
}
//连接失败
private void CallConnFailed(Exception ex)
{
if (OnConnFailedHandle != null)
{
OnConnFailedHandle(ex.Message);
}
}
#endregion
/// <summary>
/// 发送心跳
/// </summary>
/// <returns></returns>
private IEnumerator HeartEnumerator()
{
while (isHeart && isConn)
{
Send(1, "heart");
yield return new WaitForSeconds(50);
}
}
/// <summary>
/// 自动重连
/// </summary>
/// <returns></returns>
private IEnumerator AutoConn()
{
while (isAutoConn)
{
if (isConn == false && curConnCount <= reConnCount)
{
//Tools.ShowTip("正在连接...",false);
Connection();
curConnCount++;
}
yield return new WaitForSeconds(1);
}
}
/// <summary>
/// 连接
/// </summary>
/// <returns></returns>
private void Connection()
{
try
{
if (isConn == false)
{
if (address == null)
{
Debug.LogError("网络未初始化");
return;
}
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(address);
//重置连接次数
curConnCount = 0;
CallConnSuccess();
ReceiveDataHandle recv = new ReceiveDataHandle(client);
recv.client.BeginReceive(recv.Bytes, recv.StartPos, recv.EndPos, SocketFlags.None, ReceiveCallback, recv);
}
}
catch (Exception ex)
{
CallConnFailed(ex);
}
}
private void Send(byte[] _bytes)
{
if (client == null || client.Connected == false)
{
Debug.Log("未连接");
//Tools.ShowTip("未连接");
return;
}
client.BeginSend(_bytes, 0, _bytes.Length, SocketFlags.None, SendCallback, null);
}
private void SendCallback(IAsyncResult ar)
{
try
{
client.EndSend(ar);
}
catch (Exception ex)
{
Debug.LogError(string.Format("发送消息失败:{0}", ex.Message));
}
}
public void Send(int cmd, string str)
{
int headerLen = ReceiveDataHandle.HeadLength;
//包内容
byte[] byteContent = Encoding.UTF8.GetBytes(str);
int contentLen = byteContent.Length;
//报文长度
byte[] header = new byte[headerLen];
ushort len = (ushort)(contentLen);
header = BitConverter.GetBytes(len);
byte[] msgType = new byte[headerLen];
msgType = BitConverter.GetBytes((ushort)cmd);
//消息包
byte[] msgPacket = new byte[len + headerLen + headerLen];
header.CopyTo(msgPacket, 0);
msgType.CopyTo(msgPacket, 2);
byteContent.CopyTo(msgPacket, 4);
//发送
Send(msgPacket);
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
ReceiveDataHandle recv = (ReceiveDataHandle)ar.AsyncState;
int recvCount = recv.client.EndReceive(ar);
if (recvCount < ReceiveDataHandle.HeadLength + ReceiveDataHandle.MsgType) //不够解析包头和协议类型
{
//断开客户端
recv.CloseConn();
CallConnClose(string.Empty);
Debug.Log(string.Format("连接已断开"));
return;
}
recv.recvDataLen = recvCount;
ProcessData(recv);
}
catch (Exception ex)
{
CallSocketError(1, ex.Message);
}
}
private void ProcessData(ReceiveDataHandle recv)
{
try
{
//获取报文长度
int bodySize = recv.GetMsgLen();
if (bodySize < 0) //不合法数据
{
//断开客户端
//recv.client.Close();
recv.CloseConn();
CallConnClose(string.Empty);
return;
}
//获取应该要收到的字节
int packLen = bodySize + ReceiveDataHandle.HeadLength + ReceiveDataHandle.MsgType - recv.CurBufferSize;
if (recv.recvDataLen == packLen)
{
//完整包
string msg = System.Text.Encoding.UTF8.GetString(recv.Bytes, 4, bodySize);
CallRecv(recv.GetMsgType(), msg);
Debug.Log(string.Format("收到消息:{0}", msg));
recv.InitBuffer();
recv.client.BeginReceive(recv.Bytes, recv.StartPos, recv.EndPos, SocketFlags.None, new AsyncCallback(ReceiveCallback), recv);
}
else
{
if (recv.recvDataLen < packLen)
{
Debug.Log("不够继续接收");
//不够
recv.CurBufferSize += recv.recvDataLen;
recv.StartPos += recv.recvDataLen;
//继续接收
recv.client.BeginReceive(recv.Bytes, recv.StartPos, ReceiveDataHandle.BufferMaxSize - recv.CurBufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), recv);
}
else if (recv.recvDataLen > packLen)
{
Debug.Log("多余的包,分包");
//完整包
string msg = System.Text.Encoding.UTF8.GetString(recv.Bytes, 4, bodySize);
CallRecv(recv.GetMsgType(), msg);
Debug.Log(string.Format("收到消息:{0}", msg));
//多余的字节
int temp2 = recv.recvDataLen - packLen;
byte[] tempByte = new byte[ReceiveDataHandle.BufferMaxSize];
Array.Copy(recv.Bytes, packLen, tempByte, 0, temp2);
recv.Bytes = tempByte;
recv.recvDataLen = temp2;
if (temp2 < ReceiveDataHandle.HeadLength + ReceiveDataHandle.MsgType)
{
//继续接收
recv.CurBufferSize = temp2;
recv.StartPos = temp2;
recv.client.BeginReceive(recv.Bytes, recv.StartPos, ReceiveDataHandle.BufferMaxSize - recv.CurBufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), recv);
return;
}
ProcessData(recv);
}
}
}
catch (Exception ex)
{
//断开客户端
recv.CloseConn();
CallConnClose(string.Empty);
Debug.LogError(string.Format("连接已断开,处理服务端数据,出现异常", ex.Message));
return;
}
}
/// <summary>
/// 关闭连接
/// </summary>
private void DisConnection()
{
isAutoConn = false;
StopCoroutine(AutoConn());
if (client == null || !client.Connected)
{
return;
}
client.Shutdown(SocketShutdown.Both);
client.Close();
Debug.Log("连接已挂断");
}
private void OnDestroy()
{
OnConnSuccessHandle = null;
OnConnFailedHandle = null;
OnConnCloseHandle = null;
OnRecvHandle = null;
OnSocketErrorHandle = null;
DisConnection();
}
}