Повторное подключение к TCP-клиенту после тайм-аута - PullRequest
0 голосов
/ 04 марта 2020

Я только что закончил программировать автоматическую раздвижную дверь, которая управляется через приложение в C#. Приложение связывается с двигателем и перемещает дверь по TCP / IP Ethe rnet. Теперь я должен сделать еще одну версию, которая может управлять двумя дверями одновременно. Я сразу же столкнулся с проблемой, когда второй двигатель, с которым я пытался установить связь, немедленно отключился, если бы попытался отправить команду одновременно. В основном я исправил это, настроив двух фоновых рабочих. Каждый рабочий загружает все необходимые переменные из каждого двигателя каждый l oop и отправляет любые команды, поставленные в очередь. К сожалению, двигатели иногда получают переполнение команд и слабое соединение. Когда это происходит, я не могу повторно подключиться. Вот моя функция для отправки команды двигателя:

public string[] SendMotorCommand(string motorCommand, bool timeout = true, int timeoutMS = 2000)
    {
        string[] messagesReceived = null;
        if (connected)
        {
            try
            {
                //example from: http://stackoverflow.com/questions/10182751/server-client-send-receive-simple-text

                //---create a TCPClient object at the IP and port no.---
                NetworkStream nwStream = Client.GetStream();
                if (timeout)
                    nwStream.ReadTimeout = timeoutMS;
                else
                    nwStream.ReadTimeout = -1;
                byte[] bytesToSend = Encoding.ASCII.GetBytes(motorCommand + "\r");
                nwStream.Write(bytesToSend, 0, bytesToSend.Length);
                /*if (motorCommand.Contains("PR"))
                {*/
                    //---read back the text---

                    byte[] data = new byte[Client.ReceiveBufferSize];

                    int bytesRead = nwStream.Read(data, 0, data.Length);

                    string str = Encoding.ASCII.GetString(data, 0, bytesRead).Trim();

                    messagesReceived = str.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
                //}
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Failed to send or receive command " + motorCommand + " at IP " + ip);
                Debug.WriteLine(ex);
                Client.Close();
                Client = new TcpClient();
                Client.Connect(ip, 503);

            }
        }
        return (messagesReceived);
    }

Как вы можете видеть, если двигатель не может связаться, я закрываю текущий клиент и создаю его снова, однако я никогда не смогу повторно подключиться после начальной сбой связи. Единственный способ заставить их работать снова - перезапустить приложение. Тот факт, что ничего не изменилось с соединением Ethe rnet, заставляет меня думать, что я должен быть в состоянии надежно восстановить sh соединение, если оно терпит неудачу.

Вероятно, около 20 из этих команд запустить в al oop, но многие могут быть поставлены в очередь, особенно если команды не работают. Возможно ли, что куча команд ставится в очередь, и они все еще обрабатываются интерфейсом Ethe rnet? В качестве временного исправления я настроил свое приложение на перезапуск в случае сбоя команды, когда это происходит, она обычно перезагружается несколько раз, прежде чем продолжить работу. Это заставляет меня думать, что некоторые вещи еще обрабатываются.

1 Ответ

0 голосов
/ 05 марта 2020

Похоже, что это была проблема с моей очередью команд.

Вот как отправлялись мои команды:

string[] currentCommands = commands.ToArray();
                commands.Clear();

                foreach (string command in currentCommands)
                {
                    SendMotorCommand(command);
                }

Похоже, что случайно этот символ отправлялся как a команда () Не знаю, как ее отобразить, но она выглядит как маленькая буква L, которая находится выше. Это, казалось, взломало коммуникацию. Не уверен, как это происходит, поскольку я никогда не добавляю этот символ в очередь, но я подозреваю, что это как-то связано с преобразованием команд в массив. Возможно, это прервется, если команда будет добавлена ​​во время работы l oop. Сейчас я делаю проверку в функции «SendMotorCommand», чтобы пропустить команду, если это то, что отправляется. Это решает проблему, но хотелось бы знать, почему это происходит, если у кого-то есть идеи.

...