關於C#的自動重連,我是初次嘗試,試驗的情況就一種,比如服務端軟件關閉了,客戶端會開啟實時連接,只要服務端開啟偵聽,客戶端便能直接連接上,讓後發送認證信息,通知當前上線的客戶端身份。
以下是我自動重連的主要代碼:
代碼一:通訊專用類,為了方便管理和調用通訊參數,我把所有的通訊參數寫在下面的類中
/// <summary>
/// 通訊專用類
/// </summary>
public class CommunicateInfo
{
#region 通訊專用參數
/// <summary>
/// 發送信息專用字典
/// </summary>
public Dictionary<string, byte[]> Dic_SendMsg = new Dictionary<string, byte[]>();
/// <summary>
/// 消息發送專用隊列
/// </summary>
public Queue Q_MsgSend = new Queue();
/// <summary>
/// 通訊線程
/// </summary>
public Thread th_Socket;
/// <summary>
/// 通訊專用套接字
/// </summary>
public Socket soc_client;
/// <summary>
/// 心跳發送統計,收到回復清零,大於3次,認為斷線
/// </summary>
public int heartcount = 0;
/// <summary>
/// 對接能否放料盤
/// </summary>
public bool putplate = false;
/// <summary>
/// 對接能否取料盤
/// </summary>
public bool takeplate = false;
/// <summary>
/// 通知流水线取放料盘成功指令
/// </summary>
public bool infosuccess;
/// <summary>
/// 流水線是否完成交換
/// </summary>
public bool exchangeexit = false;
/// <summary>
/// 是否啟動入庫
/// </summary>
public bool startinput = false;
/// <summary>
/// 是否與服務端連接成功
/// </summary>
public bool IsConnected = false;
/// <summary>
/// 服務端(流水線)ip
/// </summary>
public string ser_ip;
/// <summary>
/// 服務端端口號
/// </summary>
public string ser_port;
/// <summary>
/// 當前入料料盤編號
/// </summary>
public string inplatenum;
#endregion
}
代碼2:自動重連,和消息發送寫在了線程中,避免對UI線程的阻塞,測試中發現,服務端停止監聽后,客戶端三次沒有收到回復,會認為服務端掉線,將連接斷開,重新連接服務端。但是把服務端軟件關閉后,在執行到Socket的Connect()方法時,還是造成了UI的假死,因為該方法執行失敗時,客戶端會持續嘗試一定次數,導致需要一定時間才會跳出該方法。目前我嘗試了多種方法,比如說異步的Connect,Application.DoEvent(),延時等都沒有很好的解決該問題,網友大神有好的辦法可以指導一下
//實例化通訊類
CommunicateInfo cominfo=new CommunicateInfo();
/// <summary>
/// 通訊專用線程,實時連接服務端,實時接收數據
/// </summary>
public void CommunicateThread()
{
while (true)
{
try
{
this.Invoke((MethodInvoker)delegate
{
Application.DoEvents();
//Thread.Sleep(TimeSpan.FromMilliseconds(3000));
//return;
#region 自動連接
if (!cominfo.IsConnected)
{
//初次連接與後期自動重連
cominfo.soc_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//cominfo.soc_client.
//cominfo.soc_client.
IPAddress server_ip = IPAddress.Parse(cominfo.ser_ip);
IPEndPoint poit = new IPEndPoint(server_ip, Int32.Parse(cominfo.ser_port));
Thread.Sleep(TimeSpan.FromMilliseconds(1));
try
{
//cominfo.soc_client.BeginConnect(cominfo.ser_ip,Int32.Parse( cominfo.ser_port), new AsyncCallback(ConnectCallback1), cominfo.soc_client);
cominfo.soc_client.Connect(server_ip, Int32.Parse(cominfo.ser_port));
//allDone.WaitOne();
//Application.DoEvents();
}
catch (Exception ex)
{
//連接失敗后釋放該資源
cominfo.soc_client.Close();
//cominfo.soc_client.Disconnect(true);
//cominfo.soc_client.Dispose();
return;
//throw;
}
//等待3s再啟動連接
//Thread.Sleep(TimeSpan.FromSeconds(5));
if (cominfo.soc_client.Connected)
{
cominfo.IsConnected = true;
//發送堆垛機編號認證
cominfo.soc_client.Send(assembly.BT_ConnectServer("0" + Stacknum[1].ToString()));
//心跳發送啟動
tm_heart.Interval = 3000;
tm_heart.Start();
}
}
#endregion
else
{
byte[] Rec = null;
string txtMsg = "";
//獲取端口可用數據長度
int recLen = cominfo.soc_client.Available;
if (recLen > 0)
{
Rec = new byte[recLen];
cominfo.soc_client.Receive(Rec);
//解析消息
//AddErrMsg()
MsgDetail(Rec);
}
}
//發送消息
if (cominfo.Q_MsgSend.Count > 0 && cominfo.soc_client.Connected)
{
//
byte[] msg = (byte[])cominfo.Q_MsgSend.Dequeue();
cominfo.soc_client.Send(msg);
int msg_count = cominfo.Dic_SendMsg.Count;
string send_msg = "";
for (int i = 0; i < msg.Length; i++)
{
send_msg += Convert.ToString(msg[i], 16).ToUpper();
}
}
//3次沒有回復認為服務端斷線,自動斷開服務端
if (cominfo.heartcount > 3)
{
cominfo.IsConnected = false;
cominfo.soc_client.Disconnect(true);
cominfo.heartcount = 0;
tm_heart.Stop();
}
});
}
catch (Exception ex)
{
}
}
}