after a long search about reconnecting a client to a server (with a timer) I did find a way that works. well almost works.
Lets say I run 3 clients, when I shutdown the server and re-run it, only one client reconnect
seems like the problem is on the server's side, but can't figure it out.
here's my code (Base class only implements the INotifyPropertyChanged interface):
Client:
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
}
Server:
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
}
ReadClients() is working on a 3rd Thread, I think it should be on the same Thread as ListenToClients().
Related
I need to implement HTTP protocol through TCP. I already had a TCP/IP client-server program which had been working absolutely fine.
Now, I have done some minor change in the source code so that it behaves as an HTTP client-server. But, unfortunately it stopped working.
The following code ...
public void Write(string str)
{
if (IsConnected)
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);
writer.Write(strBytes);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
is changed to:
public void Write(string str)
{
if (IsConnected)
{
byte[] send = Encoding.ASCII.GetBytes(str);
writer.Write(send);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
StreamReader sr = new StreamReader(stream);
string str = sr.ReadToEnd();
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
What is the issue here?
Detailed Source Code
The following class is used by both server program and client program.
modified:
namespace MyClientServer
{
public class ClientClass
{
private string Host { get; set; }
private int Port { get; set; }
private bool IsConnected = false;
public string ID { get; private set; }
public TcpClient Tcp { get; private set; }
NetworkStream stream;
private StreamReader sr;
private StreamWriter writer;
public ClientClass()
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
}
//constructor for server program.
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
IsConnected = true;
stream = Tcp.GetStream();
sr = new StreamReader(stream);
writer = new StreamWriter(stream);
ID = Read();
Console.WriteLine("Client [{0}] is now connected.", ID);
}
public bool Connect()
{
if (IsConnected == false)
{
Console.WriteLine("Client [{0}] is now connected.", ID);
IsConnected = true;
Tcp = new TcpClient(Host, Port);
stream = Tcp.GetStream();
sr = new StreamReader(stream);
writer = new StreamWriter(stream);
return true;
}
return false;
}
//constructor for client.
public ClientClass(string host, int port)
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
Host = host;
Port = port;
}
public void Write(string str)
{
if (IsConnected)
{
byte[] send = Encoding.ASCII.GetBytes(str);
writer.Write(send);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
StreamReader sr = new StreamReader(stream);
string str = sr.ReadToEnd();
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void PrintID()
{
Console.WriteLine("Client ID = {0}", ID);
}
public void SendIdToServer()
{
this.Write(ID);
}
public bool Disconnect()
{
if (IsConnected)
{
if (Tcp != null)
{
Tcp.Close();
Tcp = null;
Console.WriteLine("\nClient [{0}] is now disconnected.", ID);
return true;
}
}
return false;
}
}
}
original:
namespace MyClientServer
{
public class ClientClass
{
private string Host { get; set; }
private int Port { get; set; }
private bool IsConnected = false;
public string ID { get; private set; }
public TcpClient Tcp { get; private set; }
private BinaryReader reader;
private BinaryWriter writer;
public ClientClass()
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
}
//constructor for server program.
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
IsConnected = true;
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
ID = Read();
Console.WriteLine("Client [{0}] is now connected.", ID);
}
public bool Connect()
{
if (IsConnected == false)
{
Console.WriteLine("Client [{0}] is now connected.", ID);
IsConnected = true;
Tcp = new TcpClient(Host, Port);
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
return true;
}
return false;
}
//constructor for client.
public ClientClass(string host, int port)
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
Host = host;
Port = port;
}
public void Write(string str)
{
if (IsConnected)
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);
writer.Write(strBytes);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void PrintID()
{
Console.WriteLine("Client ID = {0}", ID);
}
public void SendIdToServer()
{
this.Write(ID);
}
public bool Disconnect()
{
if (IsConnected)
{
if (Tcp != null)
{
Tcp.Close();
Tcp = null;
Console.WriteLine("\nClient [{0}] is now disconnected.", ID);
return true;
}
}
return false;
}
}
}
I took the advice of #Jimi and also took a look at the source code from this link.
Now my source code looks like the following:
public string Read()
{
if (IsConnected)
{
byte[] buffer = new byte[Tcp.ReceiveBufferSize];//create a byte array
int bytesRead = stream.Read(buffer, 0, Tcp.ReceiveBufferSize);//read count
string str = Encoding.ASCII.GetString(buffer, 0, bytesRead);//convert to string
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void Write(string str)
{
if (IsConnected)
{
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(str);
stream.Write(bytesToSend, 0, bytesToSend.Length);
stream.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
and, it is working fine.
The following source code polls for incoming client connections.
class ServerForm : Form
{
//...
void PollIncomingClientConns(TcpListener listener)
{
listener.Start();
_keepPolling = true;
try
{
while (_keepPolling)
{
ClientClass client = new ClientClass(listener);
ClientDictionary.Add(client.ID, client);
SetStringToTextBox("Client [" + client.ID + "] is now connected.");
Thread thread = new Thread(delegate()
{
ReadFromClient(client);
});
thread.IsBackground = true;
thread.Start();
}
_tcplistener.Server.Close();
_tcplistener.Server.Dispose();
_tcplistener = null;
}
catch (Exception ex)
{
var inner = ex.InnerException as SocketException;
if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
{
SetStringToTextBox("Disconnected");
}
else
{
SetStringToTextBox(ex.Message);
}
listener.Stop();
}
}
void ReadFromClient(ClientClass client)
{
try
{
while (true)
{
string str = client.Read();
SetStringToTextBox("[" + client.ID + "] says: " + str);
switch (str)
{
// ... service client requests ...
// ... text messages ...
}
if (!client.Tcp.Connected)
{
SetStringToTextBox("[" + client.ID + "] is disconnected.");
client.Close();
break;
}
}
}
catch
{
client.Close();
}
}
// ...
}
In order to shut down the server, I am clicking, say, a button and setting _keepPolling to false.
But, on the client-side, I am finding that the client is still able to connect to the server. I.e. the server isn't shut down.
How can I solve this issue?
Relevant Source Code
The following is the client source code,
public class ClientClass
{
public string ID { get; private set; }
public string Host { get; set; }
public int Port { get; set; }
public TcpClient Tcp { get; private set; }
private BinaryReader reader;
private BinaryWriter writer;
/// <summary>
/// Creates a clienbt at the Client-end.
/// This requires Host and Post property to be set.
/// </summary>
public ClientClass()
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
}
/// <summary>
/// Creates a client at the Client-end.
/// </summary>
/// <param name="host"></param>
/// <param name="port"></param>
public ClientClass(string host, int port)
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
Host = host;
Port = port;
}
/// <summary>
/// creates a proxy-client at the Server-end.
/// </summary>
/// <param name="listener"></param>
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
ID = Read();
}
/// <summary>
/// Connects the client to the server.
/// </summary>
/// <returns></returns>
public bool Connect()
{
bool is_connected = IsConnected();
if (!is_connected)
{
Tcp = new TcpClient(Host, Port);
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
return true;
}
else if (is_connected)
{
return true;
}
else return false;
}
public bool IsConnected()
{
if (Tcp == null)
{
return false;
}
else
{
Socket s = Tcp.Client;
bool part1 = s.Poll(1000, SelectMode.SelectRead);
bool part2 = (s.Available == 0);
if ((part1 && part2) || !s.Connected)
return false;
else
return true;
}
}
public void Write(string str)
{
if (IsConnected())
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);
writer.Write(strBytes);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected())
{
byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void PrintID()
{
Console.WriteLine("Client ID = {0}", ID);
}
public void SendIdToServer()
{
this.Write(ID);
}
public bool Close()
{
if (IsConnected())
{
if (Tcp != null)
{
Tcp.Close();
Tcp = null;
return true;
}
}
return false;
}
}
Edit:
class ServerForm : Form
{
// ...
private void startToolStripMenuItem_Click(object sender, EventArgs e)
{
string ipAddress = Constants.LOCAL_HOST_IP;
int portNo = Constants.PORT_NO;
IPAddress ip = IPAddress.Parse(ipAddress);
_tcplistener = new TcpListener(ip, portNo);
// poll for clients in a 2nd thread
Thread thread = new Thread(delegate()
{
PollIncomingClientConns(_tcplistener);
});
thread.IsBackground = true;
thread.Start();
SetStringToTextBox("Server program started on address [" + ipAddress + ":" + portNo + "]");
startToolStripMenuItem.Enabled = false;
stopToolStripMenuItem.Enabled = true;
}
// ...
}
After some testing, calling _tcplistener.Stop(); is sufficient. Call it where you are setting _keepPolling to false
we Have A serverPC and more ClientPC
this system is about a server/client of CafeGame/GameNet .
My Problem: when server is Online And after that, the clients are connected all things is OK!
But When Client is Online And after that, the Server are connected We Have Problem.
An existing connection was forcibly closed by the remote host
Server Code
{
public Dictionary<string, ClientData> lstClients = new Dictionary<string, ClientData>();
private delegate void CommandReceivedEventHandler(DataPacket.DataPacket data, ClientData sender);
private event CommandReceivedEventHandler CommandReceived;
private void AcceptSocket(IAsyncResult ar)
{
TcpListener listener = (TcpListener)ar.AsyncState;
try
{
ClientData clientData = new ClientData(listener.EndAcceptSocket(ar));
int i = clientData.Socket.RemoteEndPoint.ToString().IndexOf(':');
string IPAddress = clientData.Socket.RemoteEndPoint.ToString().Substring(0, i);
clientData.IsConnected = true;
if (lstClients.ContainsKey(IPAddress))
{
lstClients.Remove(IPAddress);
lstClients.Add(IPAddress, clientData);
dicClientUserControl[IPAddress].clientData = null;
dicClientUserControl[IPAddress].clientData = clientData;
dicClientUserControl[IPAddress].clientData.IsConnected = true;
}
else
{
Dispatcher.Invoke((Action)(() =>{u = new PCu(clientData, this, 0);}));
clientData.IsOnline = false;
dicClientUserControl.Add(IPAddress, u);
lstClients.Add(IPAddress, clientData);
Dispatcher.Invoke((Action)(() => { WarpPanelClient.Children.Add(u); }));
}
clientData.Socket.BeginReceive(clientData.ReceiveBuffer, 0, clientData.ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(Receive), clientData);
listener.BeginAcceptSocket(AcceptSocket, listener);
}
catch (Exception ex)
{
listener.BeginAcceptSocket(AcceptSocket, listener);
}
}
private void Receive(IAsyncResult ar)
{
ClientData clientData = (ClientData)ar.AsyncState;
SocketError err;
int byteReceived = clientData.Socket.EndReceive(ar, out err);
if (err != SocketError.Success)
{
byteReceived = 0;
clientData.IsConnected = false;
clientData.IsOnline = false;
}
clientData.IsConnected = true;
DataPacket.DataPacket data = DataPacket.DataPacket.FromByte(clientData.ReceiveBuffer);
CommandReceived.Invoke(data, clientData);
try
{
clientData.Socket.BeginReceive(clientData.ReceiveBuffer, 0, clientData.ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(Receive), clientData);
}
catch (SocketException ex)
{
clientData.IsConnected = false;
clientData.IsOnline = false;
lstClients[clientData.AddressText] = clientData;
//dicClientUserControl[clientData.AddressText] = u;
}
catch (Exception ex)
{
}
}
private bool SendCMD(DataPacket.DataPacket data)
{
try
{
else if (clientData.IsConnected)
clientData.Socket.Send(data.ToBytes());//?? Crash
return (true);
}
catch (Exception ex)
{
//An existing connection was forcibly closed by the remote host
IS_CONNECTED(false);
return false;
}
}
}
Class in Server
public class ClientData
{
public byte[] ReceiveBuffer = new byte[10240];
DataPacket.DataPacket Data = new DataPacket.DataPacket();
bool isConnected;// Connected Or Not
bool isOnline = false;// Loged in Or Not
public Socket Socket { get; private set; }
public string NameClient { get; set; }
public int Ver { get; set; }
public int id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public ClientData(Socket socket)
{
this.Socket = socket;
int i = Socket.RemoteEndPoint.ToString().IndexOf(':');
AddressText = Socket.RemoteEndPoint.ToString().Substring(0, i);
}
}
Client Code
bool isConnected;
public bool Connect(IPAddress IP, int Port, string SystemName)
{
try
{
if (isConnected == false)
{
SocketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketClient.Connect(IP, Port);
isConnected = true;
return true;
}
else
return true;
}
catch (Exception ex)
{
if (!isConnected)
{
this.Dispatcher.Invoke((Action)(() =>
{
lblError.Text = "SERVER IS OFFLINE ... !\n" + ex.Message;
}));
return false;
}
else
return true;
}
}
where is the my problem ?
I am creating a TcpServer and TcpClient that the client will connect the server automatically once the server available (keep trying). And I don't want to lose data which means that when client sending data to server and suddenly server down, it will retry again so the below MnitorMiniTcpClientOwn.SendData will keep trying until sucessful.
However there is problem in production that happens randomly where the server will receive multiple same command because of the keep trying loop in SendData request. I am not good in network programming can anyone spot defect in the code?
Client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace NewCMS.Repositories
{
public class MonitorMiniTcpClientOwn : IDisposable
{
public string ServerIP = "127.0.0.1";
public int Port = 9090;
TcpClient tc = null;
string dataFromClient = string.Empty;
NetworkStream stream = null;
Thread RunningThread = null;
public bool IsRunning = false;
public string _Name = string.Empty;
public virtual string InitialText
{
get
{
return string.Empty;
}
}
public virtual void Start(string name)
{
_Name = name;
if (tc != null)
{
Stop();
}
ThreadStart ts = new ThreadStart(StartThread);
RunningThread = new Thread(ts);
RunningThread.Start();
}
public void StopWithoutAbort()
{
if (tc != null)
{
try
{
tc.Close();
}
catch (Exception ex)
{
}
}
if (stream != null)
{
try
{
stream.Close();
}
catch (Exception ex)
{
}
}
}
public virtual void Stop()
{
try
{
IsRunning = false;
StopWithoutAbort();
if (RunningThread != null)
{
try
{
RunningThread.Abort();
}
catch { }
}
}
catch { }
}
protected void StartThread()
{
IsRunning = true;
while (IsRunning)
{
try
{
tc = new TcpClient();
tc.Connect(ServerIP, Port);
byte[] inStream = new byte[10025];
stream = tc.GetStream();
int read = 0;
while ((read = stream.Read(inStream, 0, inStream.Length)) > 0)
{
dataFromClient += System.Text.Encoding.ASCII.GetString(inStream, 0, read);
string[] strs = dataFromClient.Split('\n');
if (strs != null)
{
for (int i = 0; i < strs.Length - 1; i++)
{
ProcessCommand(tc, strs[i]);
}
if (dataFromClient.EndsWith("\n"))
{
ProcessCommand(tc, strs[strs.Length - 1]);
dataFromClient = string.Empty;
}
else
dataFromClient = strs[strs.Length - 1];
}
}
}
catch (Exception ex)
{
StopWithoutAbort();
if (IsRunning == false)
{
break;
}
IsRunning = true;
Thread.Sleep(1000);
}
}
}
public virtual void ProcessCommand(TcpClient tc, string str)
{
}
public Exception SendData(string text)
{
Exception result = null;
int tryIndex = 0;
int tryCount = 5;
while (tryIndex < tryCount)
{
tryIndex++;
try
{
byte[] bufText = Encoding.Default.GetBytes(text);
stream.Write(bufText, 0, bufText.Length);
result = null;
break;
}
catch (Exception ex)
{
result = ex;
Thread.Sleep(300);
}
}
if (result != null)
{
return result;
}
return result;
}
public void Dispose()
{
Stop();
}
}
}
Server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace NewCMS.Repositories
{
public class MonitorMiniStoreTcpServerOwn : IDisposable
{
public int Port = 9090;
public TcpListener tl = null;
public Thread RunningThread = null;
public List<Thread> RunningAcceptTcp = new List<Thread>();
public List<MyTcpServerParam> AllConnections = new List<MyTcpServerParam>();
public bool IsRunning = false;
public string _Name = string.Empty;
public virtual void Start(string name)
{
_Name = name;
if (RunningThread != null)
{
Stop();
}
ThreadStart ts = new ThreadStart(StartThread);
RunningThread = new Thread(ts);
RunningThread.Start();
}
public virtual void StopWithoutAbort()
{
if (tl != null)
{
try
{
tl.Stop();
}
catch { }
}
if (AllConnections != null)
{
try
{
for (int i = AllConnections.Count - 1; i >= 0; i--)
{
if (AllConnections[i].Stream != null)
{
try
{
AllConnections[i].Stream.Close();
}
catch { }
}
}
AllConnections.Clear();
}
catch { }
}
if (RunningAcceptTcp != null)
{
try
{
for (int i = RunningAcceptTcp.Count - 1; i >= 0; i--)
{
try
{
RunningAcceptTcp[i].Abort();
}
catch { }
}
RunningAcceptTcp.Clear();
}
catch { }
}
}
public virtual void Stop()
{
try
{
IsRunning = false;
if (tl != null)
{
try
{
tl.Stop();
}
catch (Exception ex)
{
}
}
if (AllConnections != null)
{
try
{
for (int i = AllConnections.Count - 1; i >= 0; i--)
{
if (AllConnections[i].Stream != null)
{
try
{
AllConnections[i].Stream.Close();
}
catch { }
}
}
AllConnections.Clear();
}
catch { }
}
if (RunningAcceptTcp != null)
{
try
{
for (int i = RunningAcceptTcp.Count - 1; i >= 0; i--)
{
try
{
RunningAcceptTcp[i].Abort();
}
catch { }
}
RunningAcceptTcp.Clear();
}
catch { }
}
if (RunningThread != null)
{
try
{
RunningThread.Abort();
}
catch { }
}
}
catch
{
}
}
protected void StartThread()
{
int retry = 0;
IsRunning = true;
while (IsRunning)
{
try
{
tl = new TcpListener(IPAddress.Any, Port);
tl.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
tl.Start();
break;
}
catch (Exception ex)
{
Thread.Sleep(1000);
retry++;
}
}
while (IsRunning)
{
try
{
TcpClient clientSocket = tl.AcceptTcpClient();
MyTcpServerParam p = new MyTcpServerParam();
p.Client = clientSocket;
ParameterizedThreadStart pts = new ParameterizedThreadStart(AcceptSocket);
Thread t = new Thread(pts);
//lock (RunningAcceptTcpSync)
{
RunningAcceptTcp.Add(t);
}
t.Start(p);
}
catch (Exception ex)
{
StopWithoutAbort();
if (IsRunning)
{
ThreadStart ts = new ThreadStart(StartThread);
RunningThread = new Thread(ts);
RunningThread.Start();
}
break;
}
}
}
public void AcceptSocket(object obb)
{
try
{
if (IsRunning == false) return;
byte[] bytesFrom = new byte[10025];
string dataFromClient = string.Empty;
MyTcpServerParam para = (MyTcpServerParam)obb;
NetworkStream networkStream = para.Client.GetStream();
para.Stream = networkStream;
//lock (AllConnectionsSync)
{
AllConnections.Add(para);
}
int read = 0;
while ((read = networkStream.Read(bytesFrom, 0, bytesFrom.Length)) > 0)
{
try
{
dataFromClient += System.Text.Encoding.ASCII.GetString(bytesFrom, 0, read);
string[] strs = dataFromClient.Split('\n');
if (strs != null)
{
for (int i = 0; i < strs.Length - 1; i++)
{
ProcessCommand(para, strs[i]);
}
if (dataFromClient.EndsWith("\n"))
{
ProcessCommand(para, strs[strs.Length - 1]);
dataFromClient = string.Empty;
}
else
dataFromClient = strs[strs.Length - 1];
}
}
catch (Exception ex)
{
}
}
}
catch
{
try
{
//lock (RunningAcceptTcpSync)
{
RunningAcceptTcp.Remove(Thread.CurrentThread);
}
}
catch { }
try
{
MyTcpServerParam para = (MyTcpServerParam)obb;
//lock (AllConnectionsSync)
{
AllConnections.Remove(para);
}
}
catch { }
}
}
public virtual void ProcessCommand(MyTcpServerParam param, string str)
{
}
public Exception SendData(MyTcpServerParam param, string text)
{
Exception result = null;
int tryIndex = 0;
int tryCount = 5;
while (tryIndex < tryCount)
{
try
{
tryIndex++;
byte[] bufText = Encoding.Default.GetBytes(text);
param.Stream.Write(bufText, 0, bufText.Length);
result = null;
break;
}
catch (Exception ex)
{
result = ex;
Thread.Sleep(100);
}
}
if (result != null)
{
try
{
//lock (AllConnectionsSync)
{
AllConnections.Remove(param);
}
}
catch { }
return result;
}
return result;
}
public void Dispose()
{
Stop();
}
}
}
I have this program that creates threads on which i must create queue folders and
check them for files.
Now I noticed my program failed after processing a huge number of files without problems.
I produces a UnauthorizedAccessException so I went looking for that folder and it appears
the folder has been locked out totally?!
Could this be my anti-virus blocking access or is it something I must fix on my thread?
public class worker
{
public bool Stopping = false;
private System.Timers.Timer _timer;
private List<string> _files;
#region Feedback
public event FeedbackHandler Feedback;
public delegate void FeedbackHandler(object sender, string text);
#endregion
#region Properties
private string _name;
public string Name
{
get { return _name; }
}
private string _folder;
public string Folder
{
get { return _folder; }
set { _folder = value; }
}
private string _outfolder = Path.Combine(shared.Root, "out");
public string Outfolder
{
get { return _outfolder; }
set { _outfolder = value; }
}
private string _backupfolder = Path.Combine(shared.Root, "backup");
public string Backupfolder
{
get { return _backupfolder; }
set { _backupfolder = value; }
}
private string _filter = "*.*";
public string Filter
{
get { return _filter; }
set { _filter = value; }
}
private SearchOption _subfolders = SearchOption.TopDirectoryOnly;
public bool Subfolders
{
get { return (_subfolders == SearchOption.AllDirectories); }
set { if (value) { _subfolders = SearchOption.AllDirectories; } else { _subfolders = SearchOption.TopDirectoryOnly; } }
}
#endregion
#region Constructor
public worker(string Name)
{
_name = Name;
_folder = Path.Combine(shared.Root, "queues");
_folder = Path.Combine(_folder, Name);
}
#endregion
#region Destructor
~worker()
{
}
#endregion
#region Control
public void Start()
{
Stopping = false;
Directory.CreateDirectory(_folder);
_timer = new System.Timers.Timer(1);
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
Feedback(this, "[" + _name + "] started!");
}
public void Stop()
{
Stopping = true;
Feedback(this, "[" + _name + "] stopped...");
}
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (Stopping)
{
_timer.Stop();
_files.Clear();
return;
}
_timer.Stop();
Process();
_timer.Start();
}
#endregion
void Process()
{
if (Directory.Exists(_folder))
{
_files = Directory.GetFiles(_folder, _filter, _subfolders).ToList();
foreach (string _file in _files.ToArray())
{
if (Stopping) { break; }
document _document = new document(_file);
_document.Copy(_backupfolder);
_document.Move(_outfolder);
}
_files = new List<string>();
}
}
}
public class document
{
private string _header;
#region Feedback
public event FeedbackHandler Feedback;
public delegate void FeedbackHandler(object sender, string text);
#endregion
#region Properties
private string _file;
public string File
{
get { return _file; }
}
private job _job;
public job Job
{
get { return _job; }
}
#endregion
#region Constructor
public document(string File)
{
_file = File;
_header = shared.FileOperations.ReadHeader(_file);
_job = new job(_file, _header);
_job.ReadHeader();
}
#endregion Constructor
public void Copy(string Folder)
{
string _backupfile;
_backupfile = Path.Combine(Folder,_job.Name);
_backupfile = Path.Combine(_backupfile,_job.Company);
_backupfile = Path.Combine(_backupfile, DateTime.Now.ToString("yyyy"));
_backupfile = Path.Combine(_backupfile, DateTime.Now.ToString("MMMM"));
Directory.CreateDirectory(_backupfile);
_backupfile = Path.Combine(_backupfile, Path.GetFileName(_file));
shared.FileOperations.CopyFile(_file, _backupfile, true);
}
public void Move(string Folder)
{
string _outfile;
_outfile = Path.Combine(Folder, Path.GetFileNameWithoutExtension(_file));
shared.FileOperations.MoveFile(_file, _outfile, true);
}
}
public struct shared
{
public static string Root
{
get
{
string _base = System.AppDomain.CurrentDomain.BaseDirectory.ToString();
return Directory.GetParent(_base).Parent.FullName.ToString();
}
}
public struct Patterns
{
public const string Header = #"\^?JOB\s(?<JOB>[a-zA-Z0-9]+[0-9]{3})[D]?(?<ACTION>[JFE]+)(?<COMPANY>[A-Z]{2,2})\s" +
#"(?<EMAIL>-emto=.*)?" +
#"-C(?<COPIES>[0-9]{2,2})\s" +
#"-Z""(?<PRINTER>[A-Z0-9]+)""\s" +
#"(?:\^?PAGE 01|(?<FAX>\^?FAX.*)\s\^?PAGE 01?)";
public const string Jump = #"\^PAGE\s[0-9]+";
public const string Pages = #"(\$?PAGE\s)";
public const string Fax = #"\^?FAX FROM_COMPANY\s""(?<FROM>.*)""\s" +
#"\^?FAX FROM_FAX_NUM\s""(?<FFAX>.*)""\s" +
#"\^?FAX FROM_NAME\s""(?<FNAME>.*)""\s" +
#"\^?FAX TO_FAX_NUM\s""(?<TFAX>.*)""\s" +
#"\^?FAX TO_COMPANY\s""(?<TO>.*)""\s" +
#"\^?FAX TO_NAME\s""(?<TNAME>.*)""\s" +
#"\^?FAX WHO\s""(?<WHO>.*)""\s" +
#"\^?FAX ID\s+(?<ID>.*)";
public const string Mail = #"-em([^\s=]+)=(""[^""]*""|[^\s]+)";
public const string Seperator = #"^";
}
public struct FileOperations
{
// Encoding
public static Encoding ReadEncoding = Encoding.GetEncoding(1252);
public static Encoding WriteEncoding = Encoding.UTF8;
// Timeouts
static int Timeout = 1;
static int FileTimeout = 10000; // 10 seconds/file permitted..
// Header
public static string ReadHeader(string SourceFile)
{
return ReadHeader(SourceFile, Patterns.Jump);
}
public static string ReadHeader(string SourceFile, string Beacon)
{
WaitFile(SourceFile);
string r = null;
string l = null;
try
{
StreamReader _reader = new StreamReader(SourceFile, ReadEncoding);
Match _match;
do
{
l = _reader.ReadLine();
r += l + " ";
_match = Regex.Match(l, Beacon);
} while (!_match.Success);
_reader.Close();
}
catch (Exception ex)
{
// todo
if (Debugger.IsAttached) { throw ex; }
}
return r;
}
// Read Contents
public static List<string> ReadFile(string SourceFile)
{
return ReadFile(SourceFile, Patterns.Seperator);
}
public static List<string> ReadFile(string SourceFile, string Seperator)
{
WaitFile(SourceFile);
List<string> lines = new List<string>();
try
{
StreamReader sr = new StreamReader(SourceFile, Encoding.GetEncoding(1250));
string tmp = null;
string line = null;
while (!sr.EndOfStream)
{
line = sr.ReadLine();
if (!string.IsNullOrEmpty(line) && line.Substring(0, 1) == Seperator)
{
if (!string.IsNullOrEmpty(tmp))
{
lines.Add(tmp);
}
tmp = line.Replace(Seperator, "^");
}
else
{
tmp += Environment.NewLine + line;
}
}
sr.Close();
if (!string.IsNullOrEmpty(tmp))
{
lines.Add(tmp);
}
}
catch (Exception ex)
{
// todo
if (Debugger.IsAttached) {throw ex;}
}
return lines;
}
// Write Contents
public static void WriteFile(string DestinationFile, List<string> Lines)
{
try
{
File.WriteAllLines(DestinationFile, Lines.ToArray(), WriteEncoding);
}
catch (Exception ex)
{
// todo
if (Debugger.IsAttached) { throw ex; }
}
}
public static void WriteFile(string DestinationFile, string Contents)
{
try
{
File.WriteAllText(DestinationFile, Contents);
}
catch (Exception ex)
{
// todo
if (Debugger.IsAttached) { throw ex; }
}
}
// Move File
public static void MoveFile(string SourceFile, string DestinationFile, bool Overwrite)
{
WaitFile(SourceFile);
try
{
string _count = null;
string _destination = Path.GetDirectoryName(DestinationFile);
string _file = Path.GetFileNameWithoutExtension(DestinationFile);
string _extension = Path.GetExtension(DestinationFile);
string[] _files = Directory.GetFiles(_destination, _file + "*");
if (_files.Length > 0)
{
if (Overwrite)
{
for (int x = 0; x <= _files.Length - 1; x++)
{
File.Delete(_files[x]);
}
}
else
{
_count = "_" + (_files.Length - 1).ToString("D4");
}
}
DestinationFile = Path.Combine(_destination, _file + _count + _extension);
File.Move(SourceFile, DestinationFile);
}
catch (Exception ex)
{
if (Debugger.IsAttached) { throw ex; }
}
}
public static void CopyFile(string SourceFile, string DestinationFile, bool Overwrite)
{
WaitFile(SourceFile);
try
{
string _count = null;
string _destination = Path.GetDirectoryName(DestinationFile);
string _file = Path.GetFileNameWithoutExtension(DestinationFile);
string _extension = Path.GetExtension(DestinationFile);
string[] _files = Directory.GetFiles(_destination, _file + "*");
if (_files.Length > 0)
{
if (Overwrite)
{
for (int x = 0; x <= _files.Length - 1; x++)
{
File.Delete(_files[x]);
}
}
else
{
_count = "_" + (_files.Length - 1).ToString("D4");
}
}
DestinationFile = Path.Combine(_destination, _file + _count + _extension);
File.Copy(SourceFile, DestinationFile);
}
catch (Exception ex)
{
if (Debugger.IsAttached) { throw ex; }
}
}
// Delete File
public static void DeleteFile(string SourceFile)
{
WaitFile(SourceFile);
try
{
File.Delete(SourceFile);
}
catch (Exception ex)
{
// todo
if (Debugger.IsAttached) { throw ex; }
}
}
// Check File
static void WaitFile(string SourceFile)
{
Timeout = 1;
while (!File.Exists(SourceFile))
{
System.Threading.Thread.Sleep(Timeout);
Timeout++;
if (Timeout == FileTimeout)
{
// todo
if (Debugger.IsAttached) { throw new Exception("Timout exceeded!"); }
}
}
Timeout = 1;
while (!IsFileReady(SourceFile))
{
System.Threading.Thread.Sleep(Timeout);
Timeout++;
if (Timeout == FileTimeout)
{
// todo
if (Debugger.IsAttached) { throw new Exception("Timout exceeded!"); }
}
}
}
static bool IsFileReady(String SourceFile)
{
try
{
using (FileStream inputStream = File.Open(SourceFile, FileMode.Open, FileAccess.Read, FileShare.None))
{
if (inputStream.Length > 0)
{
return true;
}
else
{
return false;
}
}
}
catch (Exception)
{
return false;
}
}
}
public struct Functions
{
public static string CleanXML(string Text)
{
Text = Text.Replace(#"&", #"&");
Text = Text.Replace(#"<", #"<");
Text = Text.Replace(#">", #">");
Text = Text.Replace(#"""", #""");
Text = Text.Replace(#"'", #"'");
return Text;
}
}
}
void Work(string Name)
{
_worker = _workers.FirstOrDefault(w => w.Name == Name);
if (_worker == null)
{
_worker = new worker(Name);
_worker.Feedback+=new worker.FeedbackHandler(Feedback);
_worker.Folder = Path.Combine(_queuefolder, Name);
_worker.Outfolder = _outfolder;
_worker.Backupfolder = _backupfolder;
_workers.Add(_worker);
Thread _thread = new Thread(_worker.Start);
_thread.Start();
_thread.Join();
}
}
To clarify what i meant:
//worker class
private volatile bool _stopping;
private Thread _thread;
public void Start()
{
_stopping = false;
Directory.CreateDirectory(_folder);
_thread = new Thread(Process);
_thread.Start();
Feedback(this, "[" + _name + "] started!");
}
public void Stop()
{
_stopping = true;
_thread.Join();
Feedback(this, "[" + _name + "] stopped...");
}
private void Process()
{
while(!_stopping)
{
......
Thread.Sleep(100);
}
}
Because the way you are using timers... It's wrong. And while its interesting to know, why windows locks the folder, you should start from doing some refactoring. It might actually solve your problem along the way.