Как получить все данные в сообщении TCP с символом конца сообщения? - PullRequest
0 голосов
/ 03 июня 2018

У меня есть клиент-серверное приложение TCP, и оно работало очень хорошо на локальной машине.Однако в ту минуту, когда я использовал клиента на другом компьютере, доставлялись только небольшие сообщения (до 20-30 байт).В ту минуту, когда клиент должен был прочитать большие данные, если бы заблокировался.Я считаю, что проблема заключается в том, что клиент не получает все данные, отправляемые в одном пакете TCP.Другими словами, у меня был один вызов tcpClient.Client.Receive (tcpBuffer) и я предположил, что tcpBuffer имеет все данные, которые он делал на локальных машинах.Теперь все сообщения, отправляемые сервером, заканчиваются байтом, уникальным для сообщения (0xFD).Я не уверен, как с этим бороться.Таким образом, один вопрос заключается в том, предоставляет ли NetworkStream.DataAvailable данные, доступные на клиенте или на сервере?Должен ли я продолжать чтение и циклическую обработку, пока не получу значение 0xFD?Как можно было бы сделать это эффективно?В общем, я хотел бы заменить tcpClient.Client.Receive (tcpBuffer) на что-то вроде следующего:

private static byte[] GetTcpResponse()
{
    int arrayLength = tcpClient.Client.Receive(tcpBuffer);
    if (tcpBuffer[arrayLength - 1] == 0xFD)
    {
       return tcpBuffer;
    }
    else
    {
        //this is where I am hung up
    }
}

Так что, где я завис, может показаться выше.Я просто делаю еще один Получить?Что делать, если еще нет данных?Спасибо, Том

1 Ответ

0 голосов
/ 03 июня 2018

TCP - это протокол, основанный на потоке , это , а не протокол на основе дейтаграмм .Вы не должны полагаться на полученные дейтаграммы, имеющие заданный размер, или на то, что ваши данные находятся на любых заданных границах дейтаграммы;и при этом вы не должны ожидать, что все ваши данные будут получены на одной дейтаграмме (или на любом заданном количестве дейтаграмм).Поэтому, когда вы говорите:

Должен ли я продолжать читать и повторять циклы, пока не получу значение 0xFD?

Да, в этом суть;, но добавьте разумный тайм-аут и правильную проверку исключений, чтобы ваше приложение не зависало в случае сбоя соединения, и вы никогда не получите это завершающее значение.

Ваш код может быть примерно таким(кроме таймаутов, проверки ошибок и т. д.);Я не проверял это, но это должно помочь вам понять:

private static byte[] GetTcpResponse()
{
    var data = new List<byte>();
    var buffer = new byte[512]; //size can be different, just an example
    var terminatorReceived = false;
    while(!terminatorReceived)
    {
        var bytesReceived = tcpClient.Client.Receive(buffer);
        if(bytesReceived > 0)
        {
            data.AddRange(buffer.Take(bytesReceived));
            terminatorReceived = data.Contains(0xFD);
        }
    }
    return data.ToArray();
}
...