1

I have these here methods:

    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();
        }
    }

This all works, but something is wrong. When I disconnect the outputWindow gets a lot of newlines before finally saying "Client: Disconnected." The longer I stay connected to the server, the longer it takes to disconnect.

I believe the timer has something to do with this issue. The timer's job is to continuously request data from the server, and output it if any is received. Is there a better way of doing it? Perhaps "wait for server to send data" - in case nothing gets sent for several seconds, I won't have to hammer the server for requests.

Is the new thread in the getDataFromServer method taken care of by the garbage collector? Or do I need to dispose it somehow? (So that I don't end up creating a whole bunch of background threads.)

  • Here is another simple example https://stackoverflow.com/questions/21510204/c-sharp-tcpclient-send-serialized-objects-using-separators – L.B Aug 18 '17 at 21:26

1 Answers1

0

You do not need a timer to listen for incoming data. This should be automatically handled for you. Each time the listening thread task is called it should get any incoming data and then finish the task so that other threads can execute.

Here I have a sample of a listening task from one of my projects. The incoming data is serialised 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);
                }
            }
        }

Here are the declarations for the objects used:

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.
0liveradam8
  • 752
  • 4
  • 18
  • How do I connect all this to what I currently have? Do I need a TCPListener? –  Aug 18 '17 at 21:21
  • 2
    This isn't really the place for me to post a tutorial on c# sockets. If you have a very specific problem you can email me (which is on my profile page). – 0liveradam8 Aug 18 '17 at 21:24