iT邦幫忙

0

[C#] tcpclient 多執行緒斷線重蓮問題

c#
  • 分享至 

  • xImage

各位大神好:

想請問讀卡機透過tcpip模組連線,想寫程式讀1621port(soyal)傳來的資料,因為目前只有一台,但是以後想說有多台,先用其他電腦主機模擬..使用非同步與多執行緒處理,但如果用電腦主機(有個連線程式跟ConsoleClient連線)模擬讀卡機,大概過5小時或過1天,連線就與主程式中斷連線,想請問要怎麼有機制自動重新連線呢?
以下ip:166.187是用電腦模擬卡機跟主程式連線 ip:192.168.20.15是讀卡機跟主程式連線
謝謝
https://ithelp.ithome.com.tw/upload/images/20220911/2009705765txl5QLS8.jpg

https://ithelp.ithome.com.tw/upload/images/20220911/20097057Fgh5tYYzIG.jpg

主程式ConsoleClient

public void ConnectToserver()
{
   int numberOfClients = 0;
   //預設主機IP
   string[] arrayIP = new string[] {"192.168.20.15", "192.168.20.16", "192.168.20.187" };  
   //先建立IPAddress物件,IP為欲連線主機之IP
   for (int i = 0; i < arrayIP.Length; i++)
   {
     string hostIP = arrayIP[i];
     IPAddress ipa = IPAddress.Parse(hostIP);
     //建立IPEndPoint
     IPEndPoint ipe = new IPEndPoint(ipa, 1621);
     //先建立一個TCPClient
     TcpClient tcpClient = new TcpClient();
       try
       {
         Console.WriteLine("讀卡機主機IP" + ipa.ToString());
         Console.WriteLine("連線至讀卡機主機中...\n");
           if (!tcpClient.ConnectAsync(ipa, 1621).Wait(1000)) //5s
                {
                   Console.WriteLine(ipa+ "連線失敗!");
                }
           if (tcpClient.Connected)
                {        
                  MultipleClient mutipleclient = new MultipleClient(tcpClient,ipa.ToString());
                  Thread myThread = new Thread(new ThreadStart(mutipleclient.Communicate));
                   numberOfClients += 1;
                   myThread.IsBackground = true;
                   myThread.Start();
                   myThread.Name = tcpClient.Client.RemoteEndPoint.ToString();                       
                 }

              else
               {
                  Console.WriteLine("連線失敗!");
               }
        }

       catch (Exception ex)
        {
              tcpClient.Close();
              Console.WriteLine(ex.Message);
         }

      } //for loop
            Console.Read();
}

MultipleClient 類別

private TcpClient mTcpClient;
        private String ip;
        public MultipleClient(TcpClient _tcpClient,String ip) /
        {
            this.mTcpClient = _tcpClient;
            this.ip = ip;
        }

        public void Communicate()
        {
            try
            {
                Console.WriteLine("連線成功aa"+this.ip.ToString());
                CommunicationBasic cb = new CommunicationBasic();
                Byte[] sendmessage = new byte[] { 0x7e, 0x04, 0x01, 0x25, 0xdb, 0x01 }; //送指令過去 看能不能讀卡
               // while (true)
                //{
                    cb.SendMsg(sendmessage, this.mTcpClient);
                    Console.WriteLine("TX:" + staticClass.ToHexString(sendmessage, sendmessage.Length)); //靜態類別不用new
                string[] array = cb.ReceiveMsg(this.mTcpClient);
                    Console.WriteLine("RX:" +array[0]); //卡機回覆的資訊,如果沒回覆會卡住
                    Console.WriteLine("字串長度:"+array[1]);
                //}
            }
            catch
            {
                Console.WriteLine("伺服器端強制關閉連線!" + this.ip.ToString());
                this.mTcpClient.Close();
            }
        }
看更多先前的討論...收起先前的討論...
皓皓 iT邦新手 3 級 ‧ 2022-09-12 09:29:14 檢舉
在一開始就先判斷TcpClient 是否為null,並且判斷TcpClient .Connect是否已連線呢,如果未連線就斷線並讓它等於null,然後再重新建立連線?
canrong iT邦新手 3 級 ‧ 2022-09-12 10:08:45 檢舉
長連接與短連接的寫法有差,send-receive在長連接上有不同的情況要處理。
mayyola iT邦研究生 2 級 ‧ 2022-09-12 12:07:26 檢舉
主程式ㄧ開始都有判斷是否有連線,通常是可連到的,是過一段時間thread的MultipleClient才判別到斷線,所以重連的機制是否寫到MultipleClient的catch 裡呢?
canrong iT邦新手 3 級 ‧ 2022-09-12 14:29:58 檢舉
這些東西都是要看需求寫的,滿難回答的,但依照經驗,長連接我遇到的情況通常是固定時間send一段訊息,receive它的ack,receive time out或者判斷斷線就是重連。
你可能需要先了解讀卡機的通訊規範,決定是寫短連接還是長連接,短連接的簡單寫法可以封裝一個TcpClient 在send-receive前先處理connect。然後依照實際情況決定哪部分出例外時要怎麼做。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
rofellos
iT邦新手 2 級 ‧ 2022-09-12 10:15:47
最佳解答

自動重新連線包含兩個功能,判斷是否斷線,判斷是否重新連線
1.我認為比較有效的方式是寫thread固定時間丟資料,跳出Exception就一定是斷線
2.寫thread查參數判斷是否重連,除了斷線也有可能其他原因需要重連

mayyola iT邦研究生 2 級 ‧ 2022-09-12 12:01:25 檢舉

1.我有想說在多執行緒下的類別MultipleClient 用loop polling ,如果有例外(斷線等任何原因)再到該類別的catch 裡寫重新連線,但不知道會不會怎樣,遲遲不敢寫..

mayyola iT邦研究生 2 級 ‧ 2022-09-12 12:02:25 檢舉

2.因為該類別的try裡可能還要寫資料庫比對幹嘛的

0
ntustzeus
iT邦新手 3 級 ‧ 2022-09-12 09:36:00

可以參考這個
或是這備

我目前是使用NetCoreServer,範例裡在OnDisconnected有執行重連
用這種套件就就不用自己維護內部的狀態,操作比較容易,而且也比較不用擔心哪個狀態沒注意到而卡住

mayyola iT邦研究生 2 級 ‧ 2022-09-12 12:03:34 檢舉

謝謝,我再查看看,看人家寫的再看自己寫的覺得好差QQ

我要發表回答

立即登入回答