Я столкнулся с проблемой, похожей на 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
в моем примере берет строку, находит корневой элемент и первый узел и в зависимости от этого десериализует сообщение во что-то полезное.