Разбор XML из TCP-соединения - PullRequest
0 голосов
/ 27 марта 2019

Я столкнулся с проблемой, похожей на this - я пытаюсь проанализировать XML, полученный от TCP, без разделителей и узнать, получил ли я полный или частичный XML.На данный момент я выбрал следующий подход: продолжайте добавлять полученные данные в строку, попробуйте разделить их с помощью var xmls = Regex.Split(newData, @"(?=<\?xml)"); и попробуйте проанализировать каждую из строк, полученных из split - если анализ выполняется правильно, это нормально, но если нет, поместите-полный XML для ввода буфера и продолжения.Вот часть кода получения, который делает это:

    string inputBuffer = "";
    private void TcpEndReceive(IAsyncResult result)
    {
        lock (tcpLock)
        {
            int bytesAvailable = 0;
            try
            {
                bytesAvailable = tcpClient.GetStream().EndRead(result);
            }
            catch (Exception ex)
            {
                log.Error("TcpEndReceive: error endRead, ", ex);
                OnStatusChanged(EReceiverStatus.ConnectionError);
                TcpClose();
            }

            if (bytesAvailable >= 0)
            {
                try
                {
                    var newData = System.Text.ASCIIEncoding.ASCII.GetString(tcp_data, 0, bytesAvailable);

                    if (!ParseMessage(newData))
                    {
                        var xmls = Regex.Split(newData, @"(?=<\?xml)");
                        foreach (var xml in xmls)
                        {
                            if (xml.Length == 0) continue;
                            if (!ParseMessage(xml))
                            {
                                inputBuffer += xml;
                            }
                        }

                        if (inputBuffer.Length == 0) return;
                        if (ParseMessage(inputBuffer))
                        {
                            inputBuffer = "";
                        }
                    }
                }
                catch (Exception ex)
                {
                    log.Error("TcpEndReceive:error reading data, ", ex);
                    OnStatusChanged(EReceiverStatus.ConnectionError);
                    TcpClose();
                }
            }
        }
        TcpBeginReceive();
    }

Теперь это может выглядеть хорошо, но это не так - если часть сообщения выходит из строя, это не будет работать.У кого-нибудь есть идеи, как это решить?ParseMessage возвращает true, если сообщение проанализировано нормально.Кроме того, может случиться так, что вы получите часть сообщения, целое сообщение (ууу!) Или даже несколько сообщений (XML) в виде одной передачи.

Любые предложения, идеи или помощь приветствуются.Запрос «простой» - получение полного или частичного XML из потока TCP, анализ работающего и ожидание поступления других фрагментов для тех, которые не могут быть проанализированы.Единственный надежный «разделитель», который вы можете использовать, это <?xml в начале каждого (действительного) XML.

[править] - Дополнительные пояснения - я не могу контролировать данные, которые мне отправляют - я не могудобавить разделители, разделители или что-нибудь.Я могу получать только те строки, которые могут быть или не быть полным XML.Некоторые сообщения содержат изображения в кодировке Base64, и они не помещаются в одно сообщение - сначала вы получаете начало XML, затем через несколько мс вы получаете изображение Base64 (без каких-либо указаний на то, что следует больше данных), а затем вы получаете конец вашего XML.Как я уже сказал, единственным надежным сигналом является <?xml в начале действительного XML (и, конечно, в начале следующего).Кроме того, существует небольшая проблема в том, что существует несколько типов сообщений с разными корневыми элементами, поэтому вы не можете просто десериализовать до class Message - у вас есть 10-15 разных.ParseMessage в моем примере берет строку, находит корневой элемент и первый узел и в зависимости от этого десериализует сообщение во что-то полезное.

...