2015-01-12 216 views
0

經過長時間的搜索重新連接客戶端到服務器(帶定時器)後,我確實找到了一種可行的方法。以及幾乎有效。C#客戶端服務器自動重新連接

假設我運行3個客戶端,當我關閉服務器並重新運行它時,只有一個客戶端重新連接
似乎問題出在服務器端,但無法弄清楚。

這裏是我的代碼(Base類只實現INotifyPropertyChanged接口):

客戶:

class RFClient : Base 
{ 
    public enum RFClientType { Sender, Receiver }; 

    #region Properties 
    System.Threading.Timer _stTimer; 

    private int serverPort; 
    private string serverIP; 

    private string _name; 
    public string Name 
    { 
     get { return _name; } 
     set { _name = value; OnPropertyChanged("Name"); } 
    } 


    private string cType { get; set; } 
    private RFClientType _clientType; 
    public RFClientType ClientType 
    { 
     get { return _clientType; } 
     set 
     { 
      _clientType = value; 
      OnPropertyChanged("ClientType"); 
     } 
    } 

    private TcpClient _tcpServer; 
    public TcpClient TcpServer 
    { 
     get { return _tcpServer; } 
     set { _tcpServer = value; OnPropertyChanged("TcpServer"); } 
    } 

    private string _msgRecieved; 
    public string MsgRecieved 
    { 
     get { return _msgRecieved; } 
     set { _msgRecieved = value; OnPropertyChanged("MsgRecieved"); } 
    } 

    private string _errorMSG; 
    public string ErrorMSG 
    { 
     get { return _errorMSG; } 
     set { _errorMSG = value; OnPropertyChanged("ErrorMSG"); } 
    } 

    #endregion 

    #region ctor 

    public RFClient(string IP, int Port, RFClientType clientType) 
    { 
     _name = Environment.UserName; 
     this._clientType = clientType; 
     if (_clientType == RFClientType.Receiver) { cType = "Receiver"; } 
     else if (_clientType == RFClientType.Sender) { cType = "Sender"; } 
     this._tcpServer = new TcpClient(); 
     this.serverIP = IP; 
     this.serverPort = Port; 
     connectToserver(this._tcpServer, this.serverIP, this.serverPort); 

    } 

    #endregion 

    #region Methods 

    public void connectToserver(TcpClient tcpServer, string IP, int Port) 
    { 
     if (tcpServer != null) 
     { 
      try 
      { 
       _tcpServer.Connect(IP, Port); 
       SendMessage("onConnect"); 
       ReadFromServer(); 
      } 
      catch (Exception ex) { _errorMSG = ex.Message; } 
     } 
    } 

    public async void ReadFromServer() 
    { 
     string message; 
     if (_stTimer != null) { _stTimer.Dispose(); } 
     await Task.Run(() => 
     { 
      while (true) 
      { 
       if (_tcpServer != null && !_tcpServer.Connected) 
       { 
        _stTimer = new System.Threading.Timer(Timer_Tick, null, 0, 15000); 
        break; 
       } 
       else 
       { 
        try 
        { 
         using (NetworkStream readStream = _tcpServer.GetStream()) 
         { 
          byte[] bytes = new byte[256]; 
          int i; 

          while ((i = readStream.Read(bytes, 0, bytes.Length)) != 0) 
          { 
           message = System.Text.Encoding.GetEncoding("Windows-1255").GetString(bytes, 0, i); 
           MsgRecieved = message; 
          } 
         } 
        } 
        catch (Exception ex) { _errorMSG = ex.Message; return; } 
       } 

      } 
     }); 
    } 

    public async void SendMessage(string Message) 
    { 
     if (!_tcpServer.Connected) 
     { 
      _errorMSG = "No Connection"; 
      return; 
     } 

     if (_tcpServer.Connected) 
     { 
      int msgSize; 
      await Task.Run(() => 
      { 
       msgSize = Message.Length; 
       byte[] buffer = Encoding.GetEncoding("Windows-1255").GetBytes("$#1type" + cType + "$#2type" + "$#1name" + _name + "$#2name" + "$#1message" + Message + "$#2message"); 
       NetworkStream serverStream = _tcpServer.GetStream(); 
       serverStream.Write(buffer, 0, buffer.Length); 
       serverStream.Flush(); 
      }); 
     } 
    } 

    public void Close() 
    { 
     this._tcpServer.Close(); 
    } 

    public void Timer_Tick(object sender) 
    { 
     _tcpServer.Close(); 
     //_tcpServer = null; 
     _tcpServer = new TcpClient(); 
     while (!_tcpServer.Connected) 
     { 
      try 
      { 
       connectToserver(_tcpServer, serverIP, serverPort); 
       break; 
      } 
      catch { ErrorMSG = "Cannot connect..."; } 
     } 
    } 

    #endregion 
} 

服務器:

class RFServer : Base 
{ 
    #region Propertirs 

    private int myPort; 

    private TcpListener serverSocket; 
    public TcpListener ServerSocket 
    { 
     get { return serverSocket; } 
     set { serverSocket = value; OnPropertyChanged("ServerSocket"); } 
    } 

    private ObservableCollection<TcpClient> myclients; 
    public ObservableCollection<TcpClient> MyClients 
    { 
     get { return myclients; } 
     set { myclients = value; OnPropertyChanged("MyClients"); } 
    } 

    private string msgRecieved; 
    public string MsgRecieved 
    { 
     get { return msgRecieved; } 
     set { msgRecieved = value; OnPropertyChanged("MsgRecieved"); } 
    } 

    private string status; 
    public string Status 
    { 
     get { return status; } 
     set { status = value; OnPropertyChanged("Status"); } 
    } 

    private string errorStatus; 
    public string ErrorStatus 
    { 
     get { return errorStatus; } 
     set { errorStatus = value; OnPropertyChanged("ErrorStatus"); } 
    } 

    private string logPath = AppDomain.CurrentDomain.BaseDirectory + "serverRole.txt"; 

    #endregion 


    #region ctor 

    public RFServer(IPAddress locallAddress, int Port) 
    { 
     this.myPort = Port; 
     try 
     { 
      if (!System.IO.File.Exists(logPath)) 
      { 
       System.IO.File.Create(logPath).Close(); 
      } 
      serverSocket = new TcpListener(locallAddress, this.myPort); 
      serverSocket.Start(); 
      Status = "Server started"; 
      writeLog(logPath, "Server started"); 
     } 
     catch (Exception ex) { writeLog(logPath, ex.Message); ErrorStatus = ex.Message; } 
    } 

    #endregion 


    #region Methods 

    public async void ListenToClients() 
    { 
     await Task.Run(() => 
     { 
      myclients = new ObservableCollection<TcpClient>(); 
      TcpClient tcpClient = new TcpClient(); 

      while (true) 
      { 
       try 
       { 
        tcpClient = serverSocket.AcceptTcpClient(); 
        ReadClients(tcpClient); 
       } 
       catch (Exception ex) { tcpClient.Close(); writeLog(logPath, string.Format(ex.Message)); ErrorStatus = ex.Message; } 
      } 
     }); 
    } 

    public async void ReadClients(TcpClient tcpClient) 
    { 
     string fullDataReceived, clientMessage, clientType, logStr; 
     string clientName = string.Empty; 

     await Task.Run(() => 
     { 
      while (tcpClient.Connected) 
      { 
       try 
       { 
        NetworkStream networkStream = tcpClient.GetStream(); 
        byte[] bytesFrom = new byte[10025]; 
        networkStream.Read(bytesFrom, 0, (int)tcpClient.ReceiveBufferSize); 
        fullDataReceived = Encoding.GetEncoding("Windows-1255").GetString(bytesFrom); 
        clientMessage = GetSubstringByString("$#1message", "$#2message", fullDataReceived); 
        clientType = GetSubstringByString("$#1type", "$#2type", fullDataReceived); 
        clientName = GetSubstringByString("$#1name", "$#2name", fullDataReceived); 
        if (clientMessage == "onConnect") 
        { 
         logStr = string.Format("Client connected -- Name: {0}, Type: {1}, Message: {2}", clientName, clientType, clientMessage); 
         writeLog(logPath, logStr); 
         if (clientType == "Receiver") 
         { 
          myclients.Add(tcpClient); 
         } 
         networkStream.Flush(); 
        } 
        else 
        { 
         logStr = string.Format("New message from {0}: {1}", clientName, clientMessage); 
         writeLog(logPath, logStr); 
         MsgRecieved = string.Format("{0}: {1}", clientName, clientMessage); 
         SendDataToClients(MsgRecieved); 
        } 
       } 
       catch (Exception ex) 
       { 
        if (string.IsNullOrWhiteSpace(clientName)) { clientName = "UnKnown"; } 
        ErrorStatus += ex.Message + Environment.NewLine; 
        tcpClient.Close(); 
        writeLog(logPath, string.Format("cannot read from client: {0}{2}Error: {1}",clientName,ex.Message,Environment.NewLine)); 
       } 
      } 
     }); 
    } 

    public async void SendDataToClients(string message) 
    { 
     if (myclients.Count > 0) 
     { 
      byte[] buffer = Encoding.GetEncoding("Windows-1255").GetBytes(message); 
      NetworkStream clientStream; 
      string logStr; 
      for (int i = 0; i <= myclients.Count - 1; i++) 
      { 
       await Task.Run(() => 
       { 
        if (((TcpClient)myclients[i]) != null && ((TcpClient)myclients[i]).Connected) 
        { 
         try 
         { 
          clientStream = ((TcpClient)myclients[i]).GetStream(); 
          clientStream.Write(buffer, 0, buffer.Length); 
          clientStream.Flush(); 
          logStr = string.Format("Message Sent to {0} Clients. ({1})", myclients.Count, message); 
          writeLog(logPath, logStr); 
          Status += "Message Sent to " + myclients.Count + " Clients." + Environment.NewLine; 
         } 
         catch 
         { 
          ((TcpClient)myclients[i]).Close(); 
          myclients.RemoveAt(i); 
          writeLog(logPath, "client disconnected..."); 
          ErrorStatus = "client disconnected..." + Environment.NewLine; 
         } 
        } 
        else 
        { 
         ((TcpClient)myclients[i]).Close(); 
         myclients.RemoveAt(i); 
         writeLog(logPath, "client disconnected..."); 
         ErrorStatus += "client disconnected..." + Environment.NewLine; 
        } 
       }); 
      } 
     } 
    } 

    /// <summary> 
    /// Trim a string between 2 delimiters (strings). 
    /// </summary> 
    /// <param name="startString">1st delimiter</param> 
    /// <param name="endString">2nd delimiter</param> 
    /// <param name="fullString">Full string</param> 
    /// <returns></returns> 
    public string GetSubstringByString(string startString, string endString, string fullString) 
    { 
     return fullString.Substring((fullString.IndexOf(startString) + startString.Length), (fullString.IndexOf(endString) - fullString.IndexOf(startString) - startString.Length)); 
    } 


    public void writeLog(string filePath, string Logcontent) 
    { 
     File.AppendAllText(filePath, DateTime.Now + " :::: " + Logcontent + Environment.NewLine); 
    } 

    public void CloseServer() 
    { 
     writeLog(logPath, "Server Stopped"); 
     this.serverSocket.Stop(); 
     this.myclients.Clear(); 
    } 

    #endregion 
} 
+0

有什麼異常你有沒有收到?據我所知, – tyh

+0

沒有例外。 –

+0

有很多方法可以改進此代碼。但是我看到的最明顯的問題可能是導致你的問題,那就是當你停止服務器時,你沒有優雅地關閉連接。這可能會使操作系統或路由器插座處於可能會阻止稍後重新連接的狀態。 –

回答

1

ReadClients()正在第3線程,我認爲這應該與ListenToClients().

相關問題