2017-08-18 2 views
1

Ich habe diese hier Methoden:TcpClient - Wie man richtig verbinden, Verbindung zu halten und trennen schließlich

private void connectToServer() { 
     client = new TcpClient(SERVER_IP, PORT_NO); 
     nwStream = client.GetStream(); 

     writer = new StreamWriter(client.GetStream()); 
     writer.AutoFlush = true; 
     connected = true; 

     getDataFromServer(); 
     rtb_inputField.Select(); 

     if (getDataTimer == null) { 
      getDataTimer = new System.Timers.Timer(); 
      getDataTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
      getDataTimer.Interval = 1000; 
      getDataTimer.Enabled = true; 
     } 
    } 

    private void disconnectFromServer() { 
     if (connected) { 
      writer.WriteLine("quit"); 
      getDataTimer.Enabled = false; 
      getDataTimer.Dispose(); 
      getDataTimer = null; 

      Thread.Sleep(1000);  //Wait 1 second 
      nwStream.Close(); 
      client.Close(); 
      rtb_outputWindow.AppendText("\n\nClient: Disconnected."); 
     } 
     connected = false; 
    } 

    private void getDataFromServer() { 
     if (connected) { 
      new Thread(() => { 
       Thread.CurrentThread.IsBackground = true; 
       byte[] bytesToRead = new byte[client.ReceiveBufferSize]; 
       int readData = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize); 
       updateOutputWindow(Encoding.Default.GetString(bytesToRead, 0, readData)); 
      }).Start(); 
     } 
    } 

    private void updateOutputWindow(string text) { 
     string newText = string.Empty; 

     if (InvokeRequired) { 
      Invoke(new MethodInvoker(delegate() { 
       updateOutputWindow(text); 
      })); 
     } 
     else { 
      newText = startRTFString; 
      newText += rtb_outputWindow.Rtf; 
      newText += replaceAnsiColorCodes(text); 

      rtb_outputWindow.Rtf = newText; 
     } 
    } 

    private void OnTimedEvent(object source, ElapsedEventArgs e) { 
     if (connected) { 
      getDataFromServer(); 
     } 
    } 

Dies alles funktioniert, aber etwas falsch ist. Wenn ich den outputWindow abbreche, bekommt er viele Zeilenumbrüche, bevor er schließlich "Client: Getrennt" sagt. Je länger ich mit dem Server verbunden bin, desto länger dauert die Verbindungstrennung.

Ich glaube, der Timer hat etwas mit diesem Problem zu tun. Die Aufgabe des Zeitgebers besteht darin, fortlaufend Daten vom Server anzufordern und sie auszugeben, falls solche empfangen werden. Gibt es einen besseren Weg? Vielleicht "warten Sie, bis der Server Daten sendet" - falls nichts für einige Sekunden gesendet wird, muss ich den Server nicht nach Anfragen hämmern.

Wird der neue Thread in der getDataFromServer-Methode vom Garbage Collector behandelt? Oder muss ich es irgendwie entsorgen? (Damit erlebe ich nicht eine ganze Reihe von Hintergrundthreads.)

+0

Hier ist ein weiteres einfaches Beispiel https://stackoverflow.com/questions/21510204/c-sharp-tcpclient-send-serialized-objects -use-separators –

Antwort

0

Sie brauchen keinen Timer, um auf eingehende Daten zu warten. Dies sollte automatisch für Sie erledigt werden. Jedes Mal, wenn die zugeleitete Thread-Task aufgerufen wird, sollte sie alle eingehenden Daten abrufen und die Task dann beenden, damit andere Threads ausgeführt werden können.

Hier habe ich eine Hörprobe von einem meiner Projekte. Die eingehenden Daten sind serialisierte Strings.

void ListeningObjectTask()// Recieves any data sent by the other user. 
     { 
      while (client != null && client.Connected)// If there is another user and they are connected. 
      { 
       try// This suppresses exceptions thrown by connection problems, such as the user losing network signal. 
       { 
        recieve = str.ReadLine();// Gets the data sent by the other user. 
        if (recieve != "")// If the user has sent data. 
        { 
         lock (recievedStrings)// Locks the buffer to add the data sent by the other user to it. 
         { 
          recievedStrings.Enqueue(recieve); 
         } 
         recieve = "";// Clears the incoming data, as it has been stored. 
        } 
       } 
       catch (Exception Ex) 
       { 
        // Ends all the other multiplayer objects as the connection has ended and they are no longer needed. 
        Disconnect(); 
        // Tells the user why they have lost connection, so that they can try to fix the problem. 
        MessageBox.Show("Network connection ended\n" + Ex); 
       } 
      } 
     } 

Hier sind die Erklärungen für die Objekte verwendet:

private TcpClient client;// Allows connections for tcp network services. 
private StreamReader str; // Provides an interface to read from a stream. 
private string recieve;// The incoming string recieved from the other user. 
readonly Queue<string> recievedStrings = new Queue<string>();// A buffer to hold incoming data from the other user. 
+0

Wie verbinde ich all das mit dem, was ich gerade habe? Brauche ich einen TCPListener? –

+2

Dies ist nicht der richtige Ort für mich, um ein Tutorial zu C# Sockets zu posten. Wenn Sie ein sehr spezifisches Problem haben, können Sie mir eine E-Mail senden (auf meiner Profilseite). – 0liveradam8

Verwandte Themen