经过长时间搜索将客户端重新连接到服务器(带有计时器)后,我找到了一种有效的方法。几乎可以工作。
假设我运行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
}
答案 0 :(得分:1)
ReadClients()
正在开发第三个线程,我认为它应该与ListenToClients().