J'ai essayé d'obtenir que mon application serveur affiche un message dans une étiquette lorsque mon client s'est déconnecté.Message affiché lorsque TCPClient se déconnecte
Actuellement, l'étiquette affiche l'adresse IP du client connecté lors du démarrage du client, mais lorsque le client est arrêté, l'adresse IP est toujours affichée dans l'étiquette.
J'ai essayé ces méthodes jusqu'à présent sans aucune chance:
// DETECT IF CLIENT DISCONNECTED
//METHOD 1
if (bytesRead == 0)
{
ClientIPLabel.Text = "(No Clients Connected)";
break;
}
//METHOD 2
if (!tcpListener.Pending())
{
ClientIPLabel.Text = "(No Clients Connected)";
}
//METHOD 3
if (tcpClient.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (tcpClient.Client.Receive(buff, SocketFlags.Peek) == 0)
{
ClientIPLabel.Text = "(No Clients Connected)";
}
Je suis sûr que c'est probablement quelque chose simple que je suis absent, je ne peux pas comprendre ce qu'il pourrait être.
EDIT: Je l'ai trouvé un peu d'une solution où lorsque je clique sur le bouton qui ferme mon application client, le client envoie un message au serveur avant la fermeture. Le serveur sait que s'il reçoit ce message particulier (dans ce cas, "SHUTDOWN CLIENT") pour changer le texte dans "ClientIPLabel.text" à "(No Clients Connected)"
Cela fonctionne pour la plupart, mais c'est une sorte de piratage, et si le client a fermé à cause d'une erreur ou d'un crash, etc. Le serveur ne sait pas qu'il s'est déconnecté, donc il affichera toujours la dernière adresse IP connue qu'il a été envoyé.
2nd EDIT: Il semble donc que cette solution de contournement ne fonctionnera pas pour moi. Après avoir ajouté cela à mon projet, pour quelque raison que ce soit, quel que soit le message que mon client envoie au serveur, le message "(No Clients Connected)" s'affiche.
Mon client est toujours connecté en fait, et recevoir des messages, mais le ClientIPLabel 'est pas étiqueté correctement
3 EDIT: Voici un extrait montrant comment j'ai obtenu mon client configuré pour envoyer des messages au serveur selon détaillé dans un de mes commentaires ci-dessous:
private void SendMessage(string msg)
{
NetworkStream clientStream = ConsoleClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
4 EDIT: Mon code serveur, avec ma solution temporaire à obtenir un message de déconnexion du client directement à partir du bouton d'arrêt du client:
public partial class Server : Form
{
private TcpListener tcpListener;
private Thread listenThread;
private delegate void WriteMessageDelegate(string msg);
public Server()
{
InitializeComponent();
Server();
}
// WAIT FOR CLIENT
private void Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
// GET CLIENT IP ADDRESS
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
string clientIPAddress = "" + IPAddress.Parse(((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
ClientIPLabel.Text = clientIPAddress;
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
// COMMUNICATE WITH CLIENT
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
// CHECK FOR CLIENT DISCONNECT
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
if (msg.Equals("Client Disconnected (" + DateTime.Now + ")"))
{
ClientIPLabel.Text = ("(No Client Connected)");
}
}
tcpClient.Close();
}
5 EDIT: J'ai mis à jour mon code, et j'ai (presque) eu le chronomètre de pulsation mis en œuvre, mais il n'est toujours pas configuré tout à fait raison ... Voici mon code:
// CHECK FOR CLIENT DISCONNECT
// SHUTDOWN BUTTON PRESSED
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
if (msg.Equals("Client Disconnected (" + DateTime.Now + ")"))
{
ClientIPLabel.Text = ("(No Client Connected)");
}
}
tcpClient.Close();
}
// CHECK FOR CONNECTION FAILED
void heartbeatTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
HandleClientComm("Check for connection");
}
catch (Exception)
{
Invoke((MethodInvoker)delegate
{
ClientIPLabel.Text = "(No Clients Connected)";
});
}
}
Le message "(No Clients Connected)" s'affiche automatiquement sur mon serveur après la minuterie, que mon client se soit déconnecté ou non, de sorte qu'il n'attrape pas correctement l'exception.
J'ai essayé de mettre en œuvre la suggestion interceptwind comme il l'écrit, mais pour une raison quelconque où je devrais avoir catch (Exception e)
Je ne suis en mesure de construire si je me débarrasser de la e
et l'écrire comme catch (Exception)
. Si j'y laisse e
, j'obtiens un avertissement disant "The variable 'e' is declared but never used"
.
De plus, je sais qu'interswind a écrit son exemple pour utiliser ma méthode SendMessage(), mais cette méthode n'est utilisée que dans mon client, donc j'ai changé le code pour essayer d'utiliser ma méthode HandleClientComm(), donc je me demande si c'est la raison pour laquelle cela ne fonctionne pas correctement. J'ai essayé de changer quelques choses, mais je n'arrive toujours pas à le faire fonctionner. Après 5 secondes, je reçois toujours le message "(No Clients Connected)" même si mon client est toujours connecté et fonctionne correctement.
6 EDIT: Je ai essayé ajuster ma méthode HandleClientComm()
pour pouvoir envoyer des messages, mais je suis quelque chose de toute évidence manqué, parce que mon « minuterie de rythme cardiaque » commute toujours mon ClientIPLabel.text à " (Aucun client connecté) "même si mon client est toujours connecté.
Voici mon code:
// COMMUNICATE WITH CLIENT
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] message = new byte[4096];
byte[] buffer = encoder.GetBytes("Send Message");
int bytesRead;
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
// START HEARTBEAT TIMER
System.Timers.Timer heartbeatTimer = new System.Timers.Timer();
heartbeatTimer.Interval = 5000;
heartbeatTimer.Elapsed += heartbeatTimer_Elapsed;
heartbeatTimer.Start();
// CHECK FOR CLIENT DISCONNECT
// SHUTDOWN BUTTON PRESSED
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
if (msg.Equals("Client Disconnected (" + DateTime.Now + ")"))
{
ClientIPLabel.Text = ("(No Client Connected)");
}
}
tcpClient.Close();
}
// CHECK FOR CONNECTION FAILED
void heartbeatTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
HandleClientComm("Check for connection");
}
catch (Exception)
{
Invoke((MethodInvoker)delegate
{
ClientIPLabel.Text = "(No Clients Connected)";
});
}
}
Votre application serveur a une interface graphique? –
Oui, il se trouve juste dans la barre d'état système, mais il a également une interface graphique de base que vous pouvez ouvrir pour afficher les messages que mon client envoie au serveur (comme un journal), mais aussi l'adresse IP du client connecté au bas de l'interface graphique. – Patrick
L'objet que vous utilisez pour écouter le client a-t-il un événement tel que "OnDisconnected" ou un événement que vous pouvez surveiller? –