-1

I have a program which uses a TCPClient and network stream to read in data from a ip and port. Messages are constantly being sent to the program at a fast pace. The program is designed to read in these messages, and translate the messages so they display the information sent to a more readable format for the user.

This seems to be working fine - for around 60 seconds. For some reason it then seems to stop reading in messages. No error messages are displayed, just no new messages come through. When I stop and start the program it works fine again, until a minute or so has passed.

Below is the code I have used. Hopefully you'll be able to see where I may have gone wrong which could cause the stream to stop getting new messages. In the main:

public MainWindow()
{
    InitializeComponent();

    client.Connect(address, port); //client, address and port are declared as public and static

    connected = true;

    if (connected == true)
    {
        readInTxtBox.Text = "Connected";
    }


    Thread t = new Thread(ReadInandOutputToTextBoxIfInvoke);
    t.IsBackground = true;
    t.Start(); //the thread is where the messages are read in
}

And this is the method:

private void ReadInandOutputToTextBoxIfInvoke()
{
    while (true)
    {
        string message = "";
        int x = 0;
        int start = 35;
        int messageLength;
        int numberOfMessages;
        NetworkStream nwStream = client.GetStream();
        try
        {
            while ((x = nwStream.ReadByte()) != start) { if (x == -1) { continue; } } //if it doesnt begin with # or has gone over then break

            //reads in message header which is length then number of messages
            messageLength = nwStream.ReadByte();
            numberOfMessages = nwStream.ReadByte();

            string messageRecieved = new string(readMessage(nwStream, messageLength - 1));
            string[] messages = messageRecieved.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);


            for (int i = 0; i < numberOfMessages; i++)
            {
                string messageToProcess = messages[i];
                char messageType = messageToProcess[0];
                switch (messageType)
                {
                    case 'h':
                        try
                        {
                            heightMsg.Translate(Utilities.ConvertHexStringToByteArray(messageToProcess.Substring(1)));
                        }
                        catch { }
                        break;
                    case 'l':
                        try
                        {
                            longWarpHeightMsg.Translate(Utilities.ConvertHexStringToByteArray(messageToProcess.Substring(1)));
                        }
                        catch { }
                        break;
                    case 's':
                        try
                        {
                            status.Translate(Utilities.ConvertHexStringToByteArray(messageToProcess.Substring(1)));
                        }
                        catch { }
                        break;
                    case 'r':
                        try
                        {
                            calibrateMsg.Translate(Utilities.ConvertHexStringToByteArray(messageToProcess.Substring(1)));
                        }
                        catch { }
                        break;
                    default:
                        break;
                }
            }

The case statement just translate the message so may not be relevent.

Update - I have added a console.writeline to my catch statements to output any errors and no errors seem to occur. Please see below the edit I have made:

switch (messageType)
{
    case 'h':
        try
        {
            heightMsg.Translate(Utilities.ConvertHexStringToByteArray(messageToProcess.Substring(1)));
        }
        catch (Exception e)
        { Console.WriteLine(e.ToString()); }
        break;
    case 'l':
        try
        {
            longWarpHeightMsg.Translate(Utilities.ConvertHexStringToByteArray(messageToProcess.Substring(1)));
        }
        catch(Exception e) { Console.WriteLine(e.ToString());  }
        break;
    case 's':
        try
        {
            status.Translate(Utilities.ConvertHexStringToByteArray(messageToProcess.Substring(1)));
        }
        catch(Exception e) { Console.WriteLine(e.ToString());  }
        break;
    case 'r':
        try
        {
            calibrateMsg.Translate(Utilities.ConvertHexStringToByteArray(messageToProcess.Substring(1)));
        }
        catch(Exception e) { Console.WriteLine(e.ToString());  }
        break;
    default:
        break;
}
abydal
  • 378
  • 1
  • 8
Lucy Copp
  • 95
  • 10
  • Well I'd *start* by removing all those empty catch blocks that are hiding any errors from you. (If something goes wrong, do you really want to just keep going without *any* indication of the problem?) – Jon Skeet Aug 04 '17 at 08:55
  • Would that cause the network stream to stop reading? – Lucy Copp Aug 04 '17 at 08:56
  • try to use Console.Writeline to trace where is the problem came from.. and also monitor your project performance if it's iether you have a variable that need to dispose or any. as well as your network too. – Vijunav Vastivch Aug 04 '17 at 08:59
  • @LucyCopp: It may be reading perfectly well, and just failing to process the messages in a way that you're not seeing due to swallowing the exceptions. You say "No error messages are displayed" - that's quite possibly because you're swallowing all the exceptions... – Jon Skeet Aug 04 '17 at 09:02
  • I have added a console.writeline to output any exceptions and no errors seem to occur – Lucy Copp Aug 04 '17 at 09:03
  • It sounds like you have to monitor your thread execution. – Vijunav Vastivch Aug 04 '17 at 09:06
  • When where your while loop change to false? – Vijunav Vastivch Aug 04 '17 at 09:08
  • The while loop should never change to false, it should always be reading in – Lucy Copp Aug 04 '17 at 09:09
  • Probably there's a problem when reading the headers, maybe the end of the previous message is read as the next message length, or something similar. – Pau C Aug 04 '17 at 09:16
  • Maybe try TcpListener class: https://stackoverflow.com/questions/19387086/how-to-set-up-tcplistener-to-always-listen-and-accept-multiple-connections – Piotr Aug 04 '17 at 09:29
  • @Piotr I have tried using a TCPListener however the I am using an external IP address, therefore it has not been working for me – Lucy Copp Aug 04 '17 at 09:30
  • But is thould also work over internet. I suppose you did port forwarding? Check this: https://stackoverflow.com/questions/13367711/c-sharp-tcplistener-external-ip and this : https://stackoverflow.com/questions/30561922/tcpclient-how-to-connect-to-an-external-ip-address – Piotr Aug 04 '17 at 09:40
  • I'd be suspicious of `readMessage` - I'm assuming it allocates a buffer and then calls `Read` - but does it check the return value/use a loop to ensure it's reading all of the data you want it to? a [mcve] would help a lot here. – Damien_The_Unbeliever Aug 04 '17 at 13:25
  • I think the reason may be that the device has to have some sort of keep alive message to keep connected, I'll let you know if that is the resolution – Lucy Copp Aug 04 '17 at 13:47

1 Answers1

0

The problem turned out to be the device I was speaking to had to receive a keep alive message within a certain amount of time, otherwise it closed the connection. It now works - I send it a keep alive message every 8 seconds.

Lucy Copp
  • 95
  • 10