TcpClient/TcpListener Probleme unter Windows Server 2016

  • VB.NET
  • .NET 4.0

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von shoddi.

    TcpClient/TcpListener Probleme unter Windows Server 2016

    Hallo liebe Leute,

    Ich bastle aktuell einen kleinen TcpServer. Dieser nimmt Verbindungen an, liest einen String vom Stream und sendet als Antwort einen String an den Client, danach
    beendet er die Verbindung und wartet auf die nächste.

    Code den ich verwende(nur der relevante Teil und etwas vereinfacht):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. While runListener
    2. client = Server.AcceptTcpClient
    3. stream = client.GetStream()
    4. streamr = New StreamReader(stream, System.Text.Encoding.ASCII)
    5. streamw = New StreamWriter(stream, System.Text.Encoding.ASCII)
    6. scString = streamr.ReadLine()
    7. Dim response As String = Chr(27) & "[1;1H" & Chr(27) & "[0K" & Chr(27) & "[2;1H" & Chr(27) & "[0K" & Chr(27) & "[3;1H" & Chr(27) & "[0K" & Chr(27) & "[4;1H" & Chr(27) & "[0K"
    8. response = response & Chr(27) & "[1;1H" & "ECHO" & Chr(27) & "[3;1H" & scString & Chr(0)
    9. streamw.WriteLine(response)
    10. streamw.Flush()
    11. stream.Close()
    12. client.Close()
    13. End While


    Das ganze funktioniert auch sehr gut, wenn ich den Server unter Windows7/WindowsServer2012 ausführen lasse.
    Lasse ich das ganze allerdings unter WindowsServer2016 ausführen, so kommen manchmal 1, manchmal 2 mal Daten von einem Client an, danach nicht mehr...
    Habe schon einiges getestet aber noch nicht wirklich eine Lösung gefunden.
    Was mir aufgefallen ist, als ich per CMD und "netstat" die Verbindungen angesehen habe:
    Unter WS2016 "hängt" die Verbindung für einige Zeit in Status "TIME_WAIT", was erklären könnte, warum keine Anfragen mehr durchkommen.
    Unter W7 ist dies nicht so.

    Hat sich in dieser Richtung etwas zwischen Win7/WinServer2012 und WinServer2016 geändert?
    Gibt es eine Möglichkeit, an dem Punkt wo ich aktuell Client.close() nutze, die Verbindung auch wirklich direkt zu beenden,
    so dass direkt wieder neue Verbindungen angenommen werden können?

    Gruß
    shoddi
    Probier doch mal in Z#12 ein streamr.ReadToEnd() noch einzubauen. (Müsste, glaub ich, so heißen).
    Aber ohne den Gesamtcode wird's ggf. Rätselraten. V.a. wissen wir auch nicht, was auf Clientseite passiert.

    btw: Guck Dir mal die Funktion String.Join an, damit kannst Du Zeile#13 und #15 ein stückweit eindampfen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Vielen Dank für die Hinweise.
    der response-String wird normalerweise an anderer Stelle gebildet, habe hier nur der Einfachheit halber einen festen String angegeben. Sieht etwas kryptisch aus, da darüber auch der/die Clients gesteuert werden.
    Die Clients sind in dem Falle Barcode Scanner welche die Antwort dann über das Display und Töne ausgeben.

    Wie gesagt, so wie es da steht, funktioniert es unter Win7 und WinServer2012, aber nicht unter WinServer2016...
    Das Problem muss irgendwo in der Verbindung zwischen Server und Client liegen. Es scheint so, dass da irgendetwas anders gehandhabt wird, was dazu führt, dass die Verbindung unter WinServer2016 für einige Zeit im Status "TIME_WAIT" gehalten wird und in älteren Versionen eben direkt abgebaut wird.
    Hallo shoddi,

    ich hatte ähnliches Problem beim Windows Server 2016. Bei mir hat sich das von selbst erledigt, als ich anstatt TcpClients Sockets verwendet habe und die Daten direkt in den NetworkStream geschrieben habe.

    Ich habe hier mal einen Code-Schnipsel aus dem C# Projekt zusammengebastelt, vielleicht hilft es dir ja.
    Server:

    C#-Quellcode

    1. private static TcpListener listener = new TcpListener(ip, port);
    2. public void Run()
    3. {
    4. listener.Start();
    5. while (true)
    6. {
    7. try
    8. {
    9. Socket socket = listener.AcceptSocket();
    10. using (NetworkStream networkStream = new NetworkStream(socket))
    11. {
    12. networkStream.Write(bytes, 0, bytes.Length);
    13. }
    14. }
    15. catch (Exception)
    16. {
    17. throw;
    18. }
    19. }
    20. }


    Bytes ist hier ein Base64 serialisiertes Objekt mit Delimiter.

    Beim Client baue ich dann eine Verbindung wie folgt auf:

    C#-Quellcode

    1. // Client
    2. Socket connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    3. IAsyncResult asyncResult = this.Connection.BeginConnect(address, _port, null, null);
    4. asyncResult.AsyncWaitHandle.WaitOne(timeout, true);
    5. if (this.Connection.Connected)
    6. {
    7. this.Connection.EndConnect(asyncResult);
    8. }
    9. else
    10. {
    11. this.Connection.Close();
    12. }


    Wenn ich morgen Zeit habe, dann kann ich dir den Code auch gerne nochmal in schön geben, dass hier ist nur schnell aus ILSpy zusammen kopiert.

    LG