add
This commit is contained in:
365
Assets/CoolapeFrame/Scripts/net/Tcp.cs
Normal file
365
Assets/CoolapeFrame/Scripts/net/Tcp.cs
Normal file
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
********************************************************************************
|
||||
*Copyright(C),coolae.net
|
||||
*Author: chenbin
|
||||
*Version: 2.0
|
||||
*Date: 2017-01-09
|
||||
*Description: tcp
|
||||
*Others:
|
||||
*History:
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using XLua;
|
||||
|
||||
namespace Coolape
|
||||
{
|
||||
#if !UNITY_WEBGL
|
||||
public delegate void TcpDispatchDelegate(object data, Tcp tcp);
|
||||
public class Tcp : MonoBehaviour
|
||||
{
|
||||
public string host;
|
||||
public int port;
|
||||
public bool connected = false;
|
||||
public bool serializeInMainThread = true;
|
||||
//是否连接
|
||||
public bool isStopping = false;
|
||||
const int MaxReConnectTimes = 0;
|
||||
public static int __maxLen = 1024 * 1024;
|
||||
|
||||
System.Threading.Timer timer;
|
||||
public USocket socket;
|
||||
int reConnectTimes = 0;
|
||||
public const string CONST_Connect = "connectCallback";
|
||||
public const string CONST_OutofNetConnect = "outofNetConnect";
|
||||
TcpDispatchDelegate mDispatcher;
|
||||
byte[] tmpBuffer = new byte[__maxLen];
|
||||
|
||||
public virtual void init(string host, int port)
|
||||
{
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Init the specified host, port and dispatcher.
|
||||
/// </summary>
|
||||
/// <param name="host">Host.</param>
|
||||
/// <param name="port">Port.</param>
|
||||
/// <param name="dispatcher">Dispatcher,当接收到数据并解析成功后将调用该方法.</param>
|
||||
public virtual void init(string host, int port, TcpDispatchDelegate dispatcher)
|
||||
{
|
||||
mDispatcher = dispatcher;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void connect()
|
||||
{
|
||||
connect(null);
|
||||
}
|
||||
public void connect(object obj)
|
||||
{
|
||||
if (socket != null)
|
||||
{
|
||||
stop();
|
||||
}
|
||||
isStopping = false;
|
||||
socket = new USocket(host, port);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Debug.Log("connect ==" + host + ":" + port);
|
||||
#endif
|
||||
//异步连接
|
||||
socket.connectAsync(onConnectStateChg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ons the connect state chg. 当连接状态发生变化时
|
||||
/// </summary>
|
||||
/// <param name="s">S.</param>
|
||||
/// <param name="result">Result. 其实是bool类型,
|
||||
/// 当为true表示连接成功,false时表示没有连接成功或连接断开</param>
|
||||
public virtual void onConnectStateChg(USocket s, object result)
|
||||
{
|
||||
ArrayList list = result as ArrayList;
|
||||
bool isConnected = (bool)list[0];
|
||||
int retCode = (int)list[1];
|
||||
string msg = (string)list[2];
|
||||
if (isConnected)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
Debug.Log("connectCallback success");
|
||||
#endif
|
||||
connected = true;
|
||||
reConnectTimes = 0;
|
||||
socket.ReceiveAsync(onReceive);
|
||||
enqueueData(CONST_Connect);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("connectCallback fail" + host + ":" + port + "," + isStopping);
|
||||
connected = false;
|
||||
if (!isStopping)
|
||||
{
|
||||
outofNetConnect(retCode, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void outofNetConnect(int code, string msg)
|
||||
{
|
||||
if (isStopping)
|
||||
return;
|
||||
if (reConnectTimes < MaxReConnectTimes)
|
||||
{
|
||||
reConnectTimes++;
|
||||
Debug.LogWarning("reconnect times=" + reConnectTimes);
|
||||
if (timer != null)
|
||||
{
|
||||
timer.Dispose();
|
||||
}
|
||||
timer = TimerEx.schedule(connect, null, 5000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timer != null)
|
||||
{
|
||||
timer.Dispose();
|
||||
}
|
||||
timer = null;
|
||||
outofLine(socket, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void outofLine(USocket s, object obj)
|
||||
{
|
||||
if (!isStopping)
|
||||
{
|
||||
stop();
|
||||
//CLMainBase.self.onOffline();
|
||||
enqueueData(CONST_OutofNetConnect);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void stop()
|
||||
{
|
||||
isStopping = true;
|
||||
connected = false;
|
||||
if (socket != null)
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
socket = null;
|
||||
}
|
||||
|
||||
//==========================================
|
||||
public bool send(object obj)
|
||||
{
|
||||
if (socket == null)
|
||||
{
|
||||
Debug.LogWarning("Socket is null");
|
||||
return false;
|
||||
}
|
||||
object ret = packMessage(obj);
|
||||
if (isStopping || !connected)
|
||||
{
|
||||
Debug.LogWarning("isStopping =" + isStopping + "|| !connected=" + !connected);
|
||||
return false;
|
||||
}
|
||||
if (ret != null)
|
||||
{
|
||||
socket.SendAsync(ret as byte[]);
|
||||
}
|
||||
else
|
||||
{
|
||||
//这种情况可能是在组包的时候就已经发送了,还有种情况就是异常,不过其实不太可能异常,先不处理
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public object packMessage(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
return encodeData(obj);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryStream os = new MemoryStream();
|
||||
MemoryStream os2 = new MemoryStream();
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the data.数据组包准备发送
|
||||
/// </summary>
|
||||
/// <returns>The data.</returns>
|
||||
/// <param name="obj">Object.</param>
|
||||
public virtual byte[] encodeData(object obj)
|
||||
{
|
||||
os.Position = 0;
|
||||
os2.Position = 0;
|
||||
|
||||
B2OutputStream.writeObject(os, obj);
|
||||
int len = (int)os.Position;
|
||||
B2OutputStream.writeInt(os2, len);
|
||||
os2.Write(os.ToArray(), 0, len);
|
||||
int pos = (int)os2.Position;
|
||||
byte[] result = new byte[pos];
|
||||
os2.Position = 0;
|
||||
os2.Read(result, 0, pos);
|
||||
return result;
|
||||
}
|
||||
|
||||
//==========================================
|
||||
MemoryStreamPool memorystreamPool = new MemoryStreamPool();
|
||||
public void onReceive(USocket s, byte[] bytes, int len)
|
||||
{
|
||||
MemoryStream buffer = memorystreamPool.borrowObject();
|
||||
buffer.Write(bytes, 0, len);
|
||||
buffer.SetLength(len);
|
||||
enqueueData(buffer);
|
||||
}
|
||||
|
||||
object netData = null;
|
||||
MemoryStream memoryBuff = null;
|
||||
MemoryStream receivedBuffer = new MemoryStream();
|
||||
public IEnumerator wrapBuffer2Unpack()
|
||||
{
|
||||
yield return null;
|
||||
while (receivedDataQueue.Count > 0)
|
||||
{
|
||||
netData = receivedDataQueue.Dequeue();
|
||||
if (netData != null)
|
||||
{
|
||||
if (netData is string)
|
||||
{
|
||||
if (mDispatcher != null)
|
||||
{
|
||||
mDispatcher(netData, this);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
memoryBuff = netData as MemoryStream;
|
||||
receivedBuffer.Write(memoryBuff.ToArray(), 0, (int)(memoryBuff.Length));
|
||||
memorystreamPool.returnObject(memoryBuff);
|
||||
}
|
||||
}
|
||||
if (receivedBuffer.Length > 0)
|
||||
{
|
||||
receivedBuffer.SetLength(receivedBuffer.Position);
|
||||
unpackMsg(receivedBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void unpackMsg(MemoryStream buffer)
|
||||
{
|
||||
bool isLoop = true;
|
||||
object o = null;
|
||||
long usedLen = 0;
|
||||
while (isLoop)
|
||||
{
|
||||
long totalLen = buffer.Length;
|
||||
if (totalLen > 2)
|
||||
{
|
||||
usedLen = 0;
|
||||
o = parseRecivedData(buffer);
|
||||
usedLen = buffer.Position;
|
||||
if (usedLen > 0)
|
||||
{
|
||||
int leftLen = (int)(totalLen - usedLen);
|
||||
if (leftLen > 0)
|
||||
{
|
||||
buffer.Read(tmpBuffer, 0, leftLen);
|
||||
buffer.Position = 0;
|
||||
buffer.Write(tmpBuffer, 0, leftLen);
|
||||
buffer.SetLength(leftLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.Position = 0;
|
||||
buffer.SetLength(0);
|
||||
isLoop = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//buffer.Position = totalLen;
|
||||
isLoop = false;
|
||||
}
|
||||
|
||||
if (o != null && mDispatcher != null)
|
||||
{
|
||||
mDispatcher(o, this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isLoop = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the recived data.解析接收的数据,解析成功后发送给dispatcher
|
||||
/// </summary>
|
||||
/// <returns>The recived data.</returns>
|
||||
/// <param name="buffer">Buffer.</param>
|
||||
public virtual object parseRecivedData(MemoryStream buffer)
|
||||
{
|
||||
object ret = null;
|
||||
long oldPos = buffer.Position;
|
||||
buffer.Position = 0;
|
||||
long tatolLen = buffer.Length;
|
||||
long needLen = B2InputStream.readInt(buffer);
|
||||
if (needLen <= 0 || needLen > __maxLen)
|
||||
{
|
||||
// 网络Number据错误。断isOpen网络
|
||||
outofLine(this.socket, false);
|
||||
//this.stop();
|
||||
return null;
|
||||
}
|
||||
long usedLen = buffer.Position;
|
||||
if (usedLen + needLen <= tatolLen)
|
||||
{
|
||||
ret = B2InputStream.readObject(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
//说明长度不够
|
||||
buffer.Position = oldPos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
//======================================================================
|
||||
//======================================================================
|
||||
public Queue receivedDataQueue = new Queue();
|
||||
|
||||
public void enqueueData(object obj)
|
||||
{
|
||||
receivedDataQueue.Enqueue(obj);
|
||||
if (!serializeInMainThread)
|
||||
{
|
||||
StartCoroutine(wrapBuffer2Unpack());
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
if (serializeInMainThread && receivedDataQueue.Count > 0)
|
||||
{
|
||||
StartCoroutine(wrapBuffer2Unpack());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user