C#客户端服务器自动重新连接

时间:2015-01-12 21:27:20

标签: c# wpf client-server tcpclient tcplistener

经过长时间搜索将客户端重新连接到服务器(带有计时器)后,我找到了一种有效的方法。几乎可以工作。

假设我运行3个客户端,当我关闭服务器并重新运行它时,只有一个客户端重新连接
似乎问题出现在服务器端,但无法弄清楚。

这是我的代码(基类只实现了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
}

1 个答案:

答案 0 :(得分:1)

ReadClients()正在开发第三个线程,我认为它应该与ListenToClients().

在同一个线程上