由于项目需要,需要研究unity插件的进程间通信
进程间通信的方式很多,不过由于unity的限制以及实际需求考虑采用TcpSocket 的方式
首先线程启动链接,会多次重连,防止掉线
public void Connect()
{
if (m_autoConnectThread != null)
{
log("已经运行");
return;
}
try
{
m_autoConnectThread = new Thread(new ThreadStart(autoConnectThreadRun));
m_autoConnectThread.Start();
}
catch
{
log("启动线程错误...");
}
}
private void autoConnectThreadRun()
{
while (true)
{
if ((m_socketSend == null) || !m_socketSend.Connected)
{
log("自动连接中...");
doConnect();
System.Threading.Thread.Sleep(2000);
}
else
{
long heartBeatTime = LYZXCommon.DateTimeToUnixMSLong(DateTime.Now);
// 大于4秒就Ping 1次
if (heartBeatTime - m_heartBeatTime > 4)
{
Send("ping");
System.Threading.Thread.Sleep(1000);
}
else
{
System.Threading.Thread.Sleep(3000);
}
}
}
}
异步连接服务器:
private void doConnect()
{
m_socketSend = new TcpClient();
log("准备连接服务器");
m_socketSend.BeginConnect(c_ip, c_port, connectAsync, null);
}
void connectAsync(IAsyncResult result)
{
if (m_socketSend.Connected)
{
m_heartBeatTime = LYZXCommon.DateTimeToUnixMSLong(DateTime.Now);
log("连接服务器成功 -> " + m_socketSend.Client.RemoteEndPoint);
//开启异步读取消息
m_buffer = new byte[c_buffseSize];
m_stream = m_socketSend.GetStream();
m_stream.BeginRead(m_buffer, 0, m_buffer.Length, readAsync, null);
}
else
{
log("连接服务器失败");
}
}
异步读取消息,先读取消息,记录心跳时间,然后开始下一次异步读取:
void readAsync(IAsyncResult result)
{
if ((m_stream == null) || (m_socketSend == null) || (!m_socketSend.Connected))
{
return;
}
try
{
int readCount = m_stream.EndRead(result);
if (readCount == 0)
{
Send("ping");
}
else
{
string msg = Encoding.UTF8.GetString(m_buffer, 0, readCount);
log("接收到消息 -> " + msg);
m_heartBeatTime = LYZXCommon.DateTimeToUnixMSLong(DateTime.Now);
}
lock (m_stream) //再次开启读取
{
Array.Clear(m_buffer, 0, m_buffer.Length);
m_stream.BeginRead(m_buffer, 0, m_buffer.Length, readAsync, null);
}
}
catch(Exception e)
{
Debug.Log("ee:" + e.Message);
}
}
发送消息:
public void Send(string str)
{
if (m_stream != null)
{
try
{
string msg = str;
byte[] buffer = new byte[1024 * 1024 * 3];
buffer = Encoding.UTF8.GetBytes(msg);
m_stream.Write(buffer, 0, buffer.Length);
log("发送消息 -> " + msg);
m_heartBeatTime = LYZXCommon.DateTimeToUnixMSLong(DateTime.Now);
}
catch (Exception e)
{
log(e.Message);
}
}
}
好了,有了异步通信,我们就可以写我们的业务代码了
整体代码如下
public class TcpSocketTest2
{
private const string c_ip = "127.0.0.1";
private const int c_port = 33333;
private const int c_buffseSize = 8192;
TcpClient m_socketSend;
NetworkStream m_stream;
byte[] m_buffer;
private Thread m_autoConnectThread;
private long m_heartBeatTime;
private bool m_showLog = true;
private void log(string msg)
{
if (m_showLog)
{
UnityEngine.Debug.Log(msg);
}
}
public void Init()
{
m_heartBeatTime = 0;
}
public void Connect()
{
if (m_autoConnectThread != null)
{
log("已经运行");
return;
}
try
{
m_autoConnectThread = new Thread(new ThreadStart(autoConnectThreadRun));
m_autoConnectThread.Start();
}
catch
{
log("启动线程错误...");
}
}
private void autoConnectThreadRun()
{
while (true)
{
if ((m_socketSend == null) || !m_socketSend.Connected)
{
log("自动连接中...");
doConnect();
System.Threading.Thread.Sleep(2000);
}
else
{
long heartBeatTime = LYZXCommon.DateTimeToUnixMSLong(DateTime.Now);
// 大于4秒就Ping 1次
if (heartBeatTime - m_heartBeatTime > 4)
{
Send("ping");
System.Threading.Thread.Sleep(1000);
}
else
{
System.Threading.Thread.Sleep(3000);
}
}
}
}
private void doConnect()
{
m_socketSend = new TcpClient();
log("准备连接服务器");
m_socketSend.BeginConnect(c_ip, c_port, connectAsync, null);
}
void connectAsync(IAsyncResult result)
{
if (m_socketSend.Connected)
{
m_heartBeatTime = LYZXCommon.DateTimeToUnixMSLong(DateTime.Now);
log("连接服务器成功 -> " + m_socketSend.Client.RemoteEndPoint);
//开启异步读取消息
m_buffer = new byte[c_buffseSize];
m_stream = m_socketSend.GetStream();
m_stream.BeginRead(m_buffer, 0, m_buffer.Length, readAsync, null);
}
else
{
log("连接服务器失败");
}
}
public void Terminated()
{
if (m_autoConnectThread != null)
{
m_autoConnectThread.Abort();
m_autoConnectThread = null;
}
if (m_stream != null)
{
m_stream.Close();
m_stream = null;
}
if (m_socketSend != null)
{
m_socketSend.Close();
m_socketSend = null;
}
}
void readAsync(IAsyncResult result)
{
if ((m_stream == null) || (m_socketSend == null) || (!m_socketSend.Connected))
{
return;
}
try
{
int readCount = m_stream.EndRead(result);
if (readCount == 0)
{
Send("ping");
}
else
{
string msg = Encoding.UTF8.GetString(m_buffer, 0, readCount);
log("接收到消息 -> " + msg);
m_heartBeatTime = LYZXCommon.DateTimeToUnixMSLong(DateTime.Now);
}
lock (m_stream) //再次开启读取
{
Array.Clear(m_buffer, 0, m_buffer.Length);
m_stream.BeginRead(m_buffer, 0, m_buffer.Length, readAsync, null);
}
}
catch(Exception e)
{
Debug.Log("ee:" + e.Message);
}
}
public void Send(string str)
{
if (m_stream != null)
{
try
{
string msg = str;
byte[] buffer = new byte[1024 * 1024 * 3];
buffer = Encoding.UTF8.GetBytes(msg);
m_stream.Write(buffer, 0, buffer.Length);
log("发送消息 -> " + msg);
m_heartBeatTime = LYZXCommon.DateTimeToUnixMSLong(DateTime.Now);
}
catch (Exception e)
{
log(e.Message);
}
}
}
}