2015-01-12 170 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().

相关问题