最近在做Unity端和服务端的Socket连接,照着网上的案例码自己的代码,遇到了很多坑,其中消耗我最多时间,并且网上找了好久都没找到答案的一个坑,这里说一下
----------------------------------------------------------------------------------------------------------------------
我连接服务端,用的都是Socket的Connect()方法(看的百度的案例。。。中坑了),然后出现了,会疯狂的报错
/// <summary>
/// 连接socket,断开后的一段时间,尝试重连
/// </summary>
void Reconnection()
{
while (isCheckConnect)
{
try
{
if ((DateTime.Now - lastHeartTime).Seconds > maxHeartInterval && SocketInstance.Connected)
{
SocketInstance.Disconnect(false);
}
Debug.Log(socketInstance.Connected);
if (!SocketInstance.Connected)
{
Debug.Log("开始连接" + SocketInstance.Connected);
//mainContext.Post((a) => { ConnectSocket(); }, null);
IPAddress ipaddress = IPAddress.Parse(ipadd);
IPEndPoint endpoint = new IPEndPoint(ipaddress, prot);
SocketInstance.Connect(endpoint);
if (SocketInstance.Connected)
{
SocketInstance.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveData), SocketInstance);
//心跳的线程
if (dictThread.ContainsKey("SendHeart"))
{
dictThread["SendHeart"].Abort();
dictThread.Remove("SendHeart");
}
Thread sendHeartThread = new Thread(new ThreadStart(SendHeart));
sendHeartThread.IsBackground = true;
dictThread.Add("SendHeart", sendHeartThread);
sendHeartThread.Start();
//数据处理的线程
if (dictThread.ContainsKey("ProcessMsg"))
{
dictThread["ProcessMsg"].Abort();
dictThread.Remove("ProcessMsg");
}
Thread processMsgThread = new Thread(new ThreadStart(ProcessMsg));
processMsgThread.IsBackground = true;
dictThread.Add("ProcessMsg", processMsgThread);
processMsgThread.Start();
var a = new RegisterCommand();
SendCommand(a, 03);
}
}
}
catch (Exception ex)
{
Debug.LogError(ex.Message);
}
Thread.Sleep((int)(reconnectionInterval * 1000));
}
Debug.Log("我这线程结束了");
}
由于我是在UnityEditor下运行的,打开unity直接连接socket并进行相关操作,所以测试起来和排查起来比较麻烦,用了各种能想到的方法测试,具体过程略过,直接说结果
问题出在Socket.Connected属性,Socket.Connected的改变时刻是在Connect()和Disconnect()方法调用的瞬间,而不是Socket完全断开或者连接的时候,Connect()和Disconnect()是需要是时间的,而且这个时间还和网络环境等因素有关,所以会出现,我判断 if (!SocketInstance.Connected)的时候出现是断连状态,但是进入里面进行重连的时候,又提示Socket已经连接,因为Disconnect()还在执行中,还未完成
最后建议:大家用Socket连接的时候,用BeginConnect()和BeginDisconnect()这两个方法可以加回调事件,来监听连接和断连完成,网上大多数教程,只是叫你简单的连接,却不适合用在正式项目中,项目中要考虑,断线重连等等状况,所以带完成回调的方法,更加适合我们来控制Socket的过程