標籤:
源碼下載
在CS程式中,斷線重連應該是一個常見的功能。
此處的斷線重連主要指的是伺服器端因為某種故障,伺服器端程式或者系統進行了重新啟動,用戶端能夠自動探測到伺服器端掉線,並嘗試重新進行串連
本程式基於來自英國的開源c#通訊架構的networkcomms(2.3.1版本)
先看一下效果
初始狀態:
當伺服器端程式關閉後,用戶端會自動探測到,並在用戶端顯示相關資訊
然後,我們設定為每隔5秒重連一次,可以自訂設定重連的次數,比如說重連50次,如果還沒有重連成功,則放棄重連
然後我們重新啟動伺服器端,用戶端會顯示重連成功.
具體步驟如下:
需要修改幾處NetworkComms2.3.1通訊架構中的代碼
第一步:修改ConnectionInfo類的NoteConnectionShutdown方法
該方法原來是:
internal void NoteConnectionShutdown() { lock (internalLocker) ConnectionState = ConnectionState.Shutdown; }View Code
修改後為:
private bool reconnectFlag = false; /// <summary> /// 是否為重串連模式 /// </summary> public bool ReconnectFlag { get { return reconnectFlag; } set { reconnectFlag = value; } } /// <summary> /// Note this connection as shutdown /// </summary> internal void NoteConnectionShutdown() { lock (internalLocker) ConnectionState = ConnectionState.Shutdown; //添加以下代碼 初始狀態為False 觸發串連狀態改變事件 if (reconnectFlag == false) { StateChanged.Raise(this, new StringEventArgs("串連出現異常")); } } //添加狀態改變事件 public event EventHandler<StringEventArgs> StateChanged;
第二步:在NetworkComms庫類中添加相關的代碼如下:
using System;using System.Collections.Generic;using System.Text;using NetworkCommsDotNet.Tools;namespace NetworkCommsDotNet{ public static class Extensions { public static void Raise<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs { if (handler != null) handler(sender, args); } } public class StringEventArgs : EventArgs { public StringEventArgs(string text) { Text = text; } public string Text { get; set; } } }namespace System.Runtime.CompilerServices{ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)] public sealed class ExtensionAttribute : Attribute { }}相關代碼
第三步:在NetworkComms靜態類中添加如下方法:
public static void ClearDic() { lock (globalDictAndDelegateLocker) { allConnectionsById.Clear(); allConnectionsByEndPoint.Clear(); oldNetworkIdentifierToConnectionInfo.Clear(); } }
如果您使用的是V3版本,代碼稍微變化:
public static void ClearDic() { lock (globalDictAndDelegateLocker) { allConnectionsByIdentifier.Clear(); allConnectionsByEndPoint.Clear(); oldNetworkIdentifierToConnectionInfo.Clear(); } }V3
用戶端代碼:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using NetworkCommsDotNet;using DPSBase;using System.Net;using System.Threading;namespace AppClient{ public partial class Form1 : Form { //串連資訊類 public ConnectionInfo connnectionInfo = null; //串連類 Connection connection; public Form1() { InitializeComponent(); } //在表單上顯示新資訊 void Form_ConnectionStatusNotify(object sender, StringEventArgs e) { if (this.InvokeRequired) { this.Invoke(new EventHandler<StringEventArgs>(this.Form_ConnectionStatusNotify), sender, e); } else { lblLink.Text = e.Text; lblLink.ForeColor = Color.Blue; } } private bool ServerNotifyClose = false; public event EventHandler<StringEventArgs> ConnectionStatusNotify; void connnectionInfo_StateChanged(object sender, StringEventArgs e) { //如果不是伺服器通知關閉,則自動重連,如果是伺服器通知關閉,則不作處理 //本Demo中沒有使用ServerNotifyClose if (ServerNotifyClose == false) { //更新串連資訊類 設定為重連模式 connnectionInfo.ReconnectFlag = true; ConnectionStatusNotify.Raise(this, new StringEventArgs("可能由於伺服器的故障,與伺服器端的串連已斷開")); int num = 0; int retryCount = 30; int retrySpanInMSecs = 5000; do { try { NetworkComms.ClearDic(); connection = TCPConnection.GetConnection(connnectionInfo); ConnectionStatusNotify.Raise(this, new StringEventArgs("重連成功")); connnectionInfo.ReconnectFlag = false; break; } catch (Exception ex) { num++; if (num < retryCount) { ConnectionStatusNotify.Raise(this, new StringEventArgs("進行中第" + num + "次重連")); Thread.Sleep(retrySpanInMSecs); } } } while (num < retryCount); } } private void button1_Click(object sender, EventArgs e) { connnectionInfo = new ConnectionInfo(txtIP.Text, int.Parse(txtPort.Text)); //如果不成功,會彈出異常資訊 connection = TCPConnection.GetConnection(connnectionInfo); button1.Enabled = false; button1.Text = "串連成功"; //訂閱串連資訊類中的串連狀態改變事件 connnectionInfo.StateChanged += new EventHandler<StringEventArgs>(connnectionInfo_StateChanged); this.ConnectionStatusNotify += new EventHandler<StringEventArgs>(Form_ConnectionStatusNotify); } //擷取水果相關資訊 private void button2_Click(object sender, EventArgs e) { if (listBox1.SelectedIndex > -1) { string resMsg = connection.SendReceiveObject<string>("ReqFruitEngName", "ResFruitEngName", 5000, listBox1.Text); MessageBox.Show("您選擇的水果的英文名稱是:" + resMsg); } else { MessageBox.Show("請選擇一項"); } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { this.Dispose(); } }}用戶端代碼
伺服器端無需額外的設定。
至此,我們的工作已經完成。
祝大家工作順利
【c#源碼】基於TCP通訊的用戶端斷線重連