hallo,
ich bin recht neu bei WPF und c# und versuche gerade eine permante verbindung mit einem tcpip client aufzubauen.
klappt erstmal wenn beide partner verbunden sind.
wenn der client die verbindung beendet, würde ich dies gerne abfangen und den server wieder auf listen setzen. wäre nett wenn mir jemand den richtigen weg zeigt.
grüße
private void initTcpMaster()
{
IPAddress ipMaster = anyIP.IsChecked == true ? IPAddress.Any : IPAddress.Parse(txtIPMaster.Text);
int portMaster = Int32.Parse(txtPortMaster.Text);
mainThread = new Thread(new ParameterizedThreadStart(mainListener));
object args = new object[2] { ipMaster, portMaster };
mainThread.Start(args);
}
private void mainListener(object data)
{
Array argArray = new object[2];
argArray = (Array)data;
IPAddress ip = (IPAddress)argArray.GetValue(0);
int port = (int)argArray.GetValue(1);
TcpListener tcplistenerM = new TcpListener(ip, port);
updateUi("listening");
try
{
tcplistenerM.Start();
while (!tcplistenerM.Pending())
{
Thread.Sleep(sleepTimeM);
}
while (true)
{
TcpClient clientM = tcplistenerM.AcceptTcpClient();
updateUi("connected");
// for multiple clients use thread
Thread tcpHandlerThreadM = new Thread(new ParameterizedThreadStart(tcphandlerM));
tcpHandlerThreadM.Start(clientM);
}
}
catch (Exception ex)
{
throw new Exception("Fehler bei Verbindungserkennung", ex);
}
}
private void tcphandlerM(object client)
{
try
{
if (tcpClientM == null)
{
tcpClientM = (TcpClient)client; // create client
so = tcpClientM.Client; // create a socket so as to get the ipaddress of the client
streamM = tcpClientM.GetStream();
}
// read data from the port
byte[] message = new byte[100];
streamM.Read(message, 0, message.Length);
receiving_dataM = Encoding.ASCII.ReadCString(message);
//get ipaddress of the client connected
ipaddress_clientM = (IPAddress.Parse(((IPEndPoint)so.RemoteEndPoint).Address.ToString())).ToString();
if (receiving_dataM == "")
{
// ???? kommt "" wenn client verbindung beendet.
updateUi("closed by client");
} else
{
// show the string on ui -> ip addres+ data
updateUi(ipaddress_clientM + " : " + receiving_dataM);
//send back, für testzwecke
// sending_data = receiving_data;
ASCIIEncoding asen = new ASCIIEncoding();
cM = asen.GetBytes(receiving_dataM);
streamM.Write(cM, 0, cM.Length);
// neuer thread
Thread tcpHandlerThreadM = new Thread(new ParameterizedThreadStart(tcphandlerM));
tcpHandlerThreadM.Start(client);
}
}
catch (Exception e)
{
updateException(e.StackTrace);
}
}
private void closeMainThread() {
// verbindungen schliessen
if (mainThread != null)
{
streamM.Flush();
streamM.Close();
tcpClientM.Close();
lblStatusM.Content = "disconnected";
mainThread = null;
}
}
//
private void updateUi(string s)
{
Func<int> del = delegate ()
{
txtMessageInMaster.AppendText(s + System.Environment.NewLine);
lblStatusM.Content =s;
lblErrorM.Content = "";
txtMessageInMaster.ScrollToEnd();
if (s == "closed by client")
{
// ????? muss man hier etwas beenden, wenn dann der client wieder verbindet, kommt auch wieder ein leeres Bytearray,
}
return 0;
};
Dispatcher.Invoke(del);
}
//for showing if any error occurred
private void updateException(string s)
{
Func<int> del = delegate ()
{
lblStatusM.Content = "";
lblErrorM.Content = "Error : " + s;
return 0;
};
Dispatcher.Invoke(del);
}
Sockets können nicht erkennen, ob der Client noch existiert bzw. "verbunden ist".
Es geht nur via Polling.
Ich hab dazu folgendes Snippet. Kenne die ursprüngliche Quelle nicht mehr.
public static bool IsConnected(this TcpClient tcpClient)
{
if ( tcpClient.Client.Poll( 0, SelectMode.SelectRead ) )
{
byte[] buff = new byte[1];
return ( tcpClient.Client.Receive(buff, SocketFlags.Peek ) > 0)
}
}
Aber warum schlägst Du Dich bei einem simplen Chat überhaupt mit Sockets rum?
Nimm doch dazu zB. SignalR, da kriegst Du sowas geschenkt.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
danke, schaue mir direkt SignalR an. und die List<T> beherzige ich gerne...
Ein Server ist normalerweise immer im Listenmodus, weil er nicht nur auf einen einzigen Client hören will. Natürlich kann er das handhaben wie er möchte, aber falls du wirklich nur einen einzigen Client haben willst würde ich auch immer "hören" und nur den einen Client akzeptieren. Sprich der muss sich anmelden und dann schließt du die Verbindung wieder wenn es nicht dein Wunsch Client ist.
Meines Wissens gibt es eine Exception wenn ein Client sich regulär beendet. Müsstest du ausprobieren.
erst einmal danke für die hilfreichen Antworten!
kurz zur Erklärung: was ich versuche in wpf zu bauen ist eine Bridge für alle möglichen Protokolle zur Verwendung in Medieninstallationen, z.B. arduino seriell, via UDP an Android Tablets, oder Android an DMX... vvvv, openframework, flash...
Bisher basiert dies überwiegend auf einem Schwung python Skripte. Schön wäre es hier eine bessere visuelle Kontrolle zu bekommen, ok, das ginge auch in python, aber parallel kann ich mir wpf etwas aneignen.
Das mit den Layern ist mir klar sein, ist aber für den ersten Test eines Protokolls nicht so wichtig, wenn klar ist wie es funzt werde ich das in Klassen zerlegen.
grüße
Dann hab ich das mit dem Chat falsch verstanden; dann ist SignalR hier eher nicht geeignet.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Die saubere Lösung ist es immer eine Ping Nachricht in das Protokoll einzubauen, die der Server alle x Sekunden schickt und die der Client dann in y Sekunde beantworten muss - Firewalls kappen gerne Verbindungen bei Inaktivität und hängende Clients möchte man auch lieber abhängen.
Exceptions gibt es nur, wenn der Client sich unsauber beendet - beim Ziehen eines Netzwerkkabels zum Beispiel sieht man nix.
Die saubere Lösung ist es immer eine Ping Nachricht in das Protokoll einzubauen, die der Server alle x Sekunden schickt und die der Client dann in y Sekunde beantworten muss
Genau! Siehe auch RFC 1459, Absatz 4.6.2. - das sind Spezifikationen, an die man sich durchaus halten kann, auch wenn man kein IRC implementiert (die Jungs haben sich dabei ja was gedacht, und IRC gibt's nun auch schon ein, zwei Tage).
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)