hi i'm david and i'm new in this site, i'm here because i have a problem with my solution of Client-Server communication.
I have created 3 classes 'STransferMessage', 'SServer' and 'SClient'.
SServer and SClient extend STransferMessage, i thought it might be the best solution because more methods are similar.
Now i describe you my problem;
All works very good on Windows Console, but when i use the same classes on Windows Forms or WPF and one client try to connect, the server crash with "The operation completed successfully" exception! no one try-catch costruct block the exception and the source aren't available.
So i decided to create a new empty form but i have had the same problem.
I can't understand why with Console works and with forms or WPF no.
these are my classes:
Dropbox folder
i'm sorry for my bad english but i'm italian.
Here the codes
STransferMessage
using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
namespace SecureTransferMessage.Communication
{
public enum TransferSystemType
{
Server,
Client
}
public class STransferMessage
{
private readonly Boolean _isServer;
private readonly TransferSystemType _type;
public STransferMessage()
{
_type = TransferSystemType.Client;
_isServer = false;
}
public STransferMessage(TransferSystemType type)
{
_type = type;
_isServer = (_type == TransferSystemType.Server) ? true : false;
}
protected internal TransferSystemType Type
{
get { return _type; }
}
protected internal Boolean IsServer
{
get { return _isServer; }
}
protected internal Boolean IsClient
{
get { return !_isServer; }
}
protected internal Boolean Write(TcpClient client, String message)
{
NetworkStream clientStream;
if (client == null)
{
return false;
}
if (client.Connected)
clientStream = client.GetStream();
else
return false;
return Write(clientStream, message);
}
protected internal String Read(TcpClient client)
{
NetworkStream clientStream;
if (client == null)
{
return null;
}
if (client.Connected)
clientStream = client.GetStream();
else
return null;
return Read(clientStream);
}
protected internal Boolean Write(NetworkStream clientStream, String message)
{
if (clientStream != null && clientStream.CanWrite)
{
var sStream = new SslStream(clientStream);
Byte[] mess = Encoding.UTF8.GetBytes(message);
try
{
clientStream.Write(mess, 0, mess.Length);
return true;
}
catch (Exception)
{
throw;
}
}
return false;
}
protected internal String Read(NetworkStream clientStream)
{
if (clientStream != null && clientStream.DataAvailable && clientStream.CanRead)
{
var readBuffer = new byte[1024];
var message = new StringBuilder();
var sStream = new SslStream(clientStream);
do
{
int bytesRead = clientStream.Read(readBuffer, 0, readBuffer.Length);
message.AppendFormat("{0}", Encoding.UTF8.GetString(readBuffer, 0, bytesRead));
} while (clientStream.DataAvailable);
return message.ToString();
}
return null;
}
protected internal Boolean SocketIdConnected(Socket nSocket)
{
if (nSocket.Connected)
{
if ((nSocket.Poll(0, SelectMode.SelectWrite)) && (!nSocket.Poll(0, SelectMode.SelectError)))
{
var buffer = new byte[1];
if (nSocket.Receive(buffer, SocketFlags.Peek) == 0)
{
return false;
}
return true;
}
return false;
}
return false;
}
}
}
SServer
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SecureTransferMessage.Communication
{
public class SServer : STransferMessage
{
#region "VARIABILI"
public const int NO_CLIENT_LIMIT = -1;
private Thread _checkClientThread;
private Dictionary<String, TcpClient> _clients;
private Boolean _isMulticast;
private TcpListener _listener;
private int _maxClient = NO_CLIENT_LIMIT;
public Dictionary<String, TcpClient> Clients
{
get { return _clients; }
}
public Boolean IsMulticast
{
get { return _isMulticast; }
}
public Boolean HasClient
{
get { return (_clients.Count > 0) ? true : false; }
}
public int MaxClient
{
get { return _maxClient; }
set { _maxClient = value; }
}
#endregion
#region "EVENTI"
public class CommunicationMessageEventArgs : EventArgs
{
public TcpClient Client;
public String ClientId;
public String Message;
public DateTime Time;
}
public event EventHandler<EventArgs> ServerStarting;
public event EventHandler<EventArgs> ServerStopping;
public event EventHandler<CommunicationMessageEventArgs> ServerReceivedMessage;
public event EventHandler<CommunicationMessageEventArgs> ServerSentMessage;
public event EventHandler<EventArgs> ClientDisconnected;
private void OnServerStarting(EventArgs e)
{
if (ServerReceivedMessage != null)
{
ServerStarting(this, e);
}
}
private void OnServerStopping(EventArgs e)
{
if (ServerSentMessage != null)
{
ServerStopping(this, e);
}
}
private void OnReceivedMessage(CommunicationMessageEventArgs e)
{
if (ServerReceivedMessage != null)
{
ServerReceivedMessage(this, e);
}
}
private void OnSentMessage(CommunicationMessageEventArgs e)
{
if (ServerSentMessage != null)
{
ServerSentMessage(this, e);
}
}
private void OnClientDisconnected(EventArgs e)
{
if (ClientDisconnected != null)
{
ClientDisconnected(this, e);
}
}
#endregion
#region "COSTRUTTORI"
public SServer(int port)
: base(TransferSystemType.Server)
{
_iniServer(port, false);
}
public SServer(int port, Boolean isMulticast)
: base(TransferSystemType.Server)
{
_iniServer(port, isMulticast);
}
#endregion
#region "PUBBLICI"
public void Start()
{
OnServerStarting(new EventArgs());
_listener.Start();
Console.WriteLine("Waiting for client..");
_listener.BeginAcceptTcpClient(AccettaClient, _listener);
_checkClientThread.Start();
}
public void Stop()
{
OnServerStopping(new EventArgs());
_listener.Stop();
_checkClientThread.Abort();
}
private void AccettaClient(IAsyncResult result)
{
var listener = (TcpListener) result.AsyncState;
TcpClient client;
try
{
DeleteDeadClients();
client = listener.EndAcceptTcpClient(result);
if (HasClient && !_isMulticast)
{
Console.WriteLine("Server full!");
Write(client, "Server full!");
}
else if (_maxClient != NO_CLIENT_LIMIT && _clients.Count >= _maxClient)
{
Console.WriteLine("Server full!");
Write(client, "Server full!");
}
else
{
String id = Guid.NewGuid().ToString();
Clients.Add(id, client);
Console.WriteLine("Client connesso!");
Console.Title = "Server [" + Clients.Count + " Client]";
}
}
catch (SocketException ex)
{
Console.WriteLine("Error accepting TCP connection: {0}", ex.Message);
return;
}
catch (ObjectDisposedException)
{
Console.WriteLine("Listen canceled.");
return;
}
listener.BeginAcceptTcpClient(AccettaClient, listener);
}
public Boolean Write(String message)
{
if (HasClient)
{
var Kclient = _clients.First();
String clientId = Kclient.Key;
if (Write(clientId, message))
{
var args = new CommunicationMessageEventArgs
{
Message = message,
Client = Kclient.Value,
ClientId = clientId,
Time = DateTime.Now
};
OnSentMessage(args);
return true;
}
else
{
return false;
}
}
return false;
}
public String Read()
{
if (HasClient)
{
var kclient = _clients.First();
String clientId = kclient.Key;
String message = Read(clientId);
if (message != null)
{
var args = new CommunicationMessageEventArgs
{
Message = message,
Client = kclient.Value,
ClientId = clientId,
Time = DateTime.Now
};
OnReceivedMessage(args);
return message;
}
return null;
}
return null;
}
public Boolean Write(String clientId, String message)
{
return Write(GetClientById(clientId), message);
}
public String Read(String clientId)
{
return Read(GetClientById(clientId));
}
public KeyValuePair<string, string> ReadFromAnyone()
{
var ret = new KeyValuePair<string, string>();
var t = new Thread(() =>
{
while (true)
{
if (ret.Key != null)
{
break;
}
}
});
t.Start();
foreach (var dclient in _clients)
{
KeyValuePair<String, TcpClient> dclient1 = dclient;
new Thread(new ThreadStart(delegate
{
Thread.Sleep(50);
String strR = this.Read(dclient1.Key);
ret = new KeyValuePair<string, string>(dclient1.Key, strR);
})).Start();
}
t.Join();
return ret;
}
public TcpClient GetClientById(String clientId)
{
TcpClient client = null;
try
{
client = _clients[clientId];
}
catch (Exception)
{
client = null;
}
return client;
}
public void KickAllClient()
{
Dictionary<string, TcpClient> tempClients = _clients;
foreach (string clientId in tempClients.Keys.ToList())
{
KickClient(clientId);
}
}
public Boolean KickClient(String clientId)
{
TcpClient client = GetClientById(clientId);
if (client != null)
{
client.GetStream().Close();
client.Close();
bool res = _clients.Remove(clientId);
OnClientDisconnected(new EventArgs());
return res;
}
return false;
}
public int BroadcastMessage(String message)
{
return _clients.Count(dclient => Write(dclient.Value, message));
}
public void Dispose()
{
KickAllClient();
_listener.Stop();
}
public static IPAddress GetLocalIpAddress()
{
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip;
}
}
return null;
}
public void DeleteDeadClients()
{
Dictionary<string, TcpClient> tempClients = _clients;
foreach (string clientId in tempClients.Keys.ToList())
{
if (!SocketIdConnected(tempClients[clientId].Client))
{
KickClient(clientId);
Console.WriteLine("Cliend disconnesso");
}
}
}
#endregion
#region "PRIVATE"
private void _iniServer(int port, Boolean isMulticast)
{
_clients = new Dictionary<String, TcpClient>();
_listener = new TcpListener(GetLocalIpAddress(), port);
_isMulticast = isMulticast;
_checkClientThread = new Thread(new ThreadStart(delegate
{
while (true)
{
if (HasClient)
{
DeleteDeadClients();
Console.Title = "Server [" + Clients.Count + " Client]";
}
else
{
Thread.Sleep(1000);
}
}
}));
}
#endregion
}
}
SClient
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.ComponentModel;
using System.Net.Security;
using SecureTransferMessage.Communication.STMException;
namespace SecureTransferMessage.Communication
{
public sealed class SClient : STransferMessage
{
private TcpClient _client = null;
private IPAddress _address = null;
private int _port = 0;
public IPAddress Address { get { return _address; } }
public int Port { get { return _port; } }
public Boolean IsConnected { get {
try
{
return _client.Connected;
}
catch (Exception)
{
return false;
}
} }
public SClient(IPAddress address,int port) : base(TransferSystemType.Client)
{
this._address = address;
this._port = port;
Connect();
}
public void Connect()
{
if (_client == null)
{
_client = new TcpClient(_address.ToString(), _port);
}
else
{
throw new SecureTransferException("La connessione con l'host è già aperta");
}
}
public Boolean TryConnect()
{
try
{
_client = new TcpClient(_address.ToString(), _port);
return true;
}
catch (Exception)
{
return false;
}
}
public void Close()
{
if (_client != null && IsConnected)
{
_client.GetStream().Close();
_client.Close();
_client = null;
}
}
public Boolean Write(String message)
{
return base.Write(_client, message);
}
public String Read()
{
return base.Read(_client);
}
}
}