случайная потеря байтов при потоковой передаче данных по сети

StackOverflow https://stackoverflow.com//questions/20011324

Вопрос

Моя проблема в том, что когда я передаю непрерывный поток данных через ЛОКАЛЬНУЮ сеть LAN, иногда в процессе теряются случайные байты.

В настоящее время код настроен на потоковую передачу около 1027 байтов или около того ~ 40 раз в секунду по локальной сети, и иногда (очень редко) один или несколько байтов теряются.

Меня сбивает с толку то, что фактический байт не «теряется», а просто устанавливается на 0 независимо от исходных данных.(Кстати, я использую TCP)

Вот код отправки:

    public void Send(byte[] data)
    {
        if (!server)
        {
            if (CheckConnection(serv))
            {
                serv.Send(BitConverter.GetBytes(data.Length));
                serv.Receive(new byte[1]);
                serv.Send(data);
                serv.Receive(new byte[1]);
            }
        }
    }

и код получения:

    public byte[] Receive()
    {
        if (!server)
        {
            if (CheckConnection(serv))
            {
                byte[] TMP = new byte[4];
                serv.Receive(TMP);
                TMP = new byte[BitConverter.ToInt32(TMP, 0)];
                serv.Send(new byte[1]);
                serv.Receive(TMP);
                serv.Send(new byte[1]);
                return TMP;
            }
            else return null;
        }
        else return null;
    }

Отправка и получение пустых байтов предназначены просто для поддержания синхронизации системы.Лично я думаю, что проблема кроется на принимающей стороне системы.хотя мне не удалось доказать, что это самолет.

Это было полезно?

Решение

Просто потому, что ты даешь Receive(TMP) массив из 4 байтов не означает, что он будет заполнять этот массив 4 байтами.Вызов приема разрешен в любом месте между 1 и TMP.Length байты в массив.Вы должны проверить возвращенный int чтобы увидеть, сколько байтов массива заполнено.

Сетевые соединения основаны на потоках, а не на сообщениях.Любые байты, которые вы передаете по каналу, просто объединяются в большую очередь и считываются на другой стороне, как только они становятся доступными.Итак, если вы отправили два массива 1,1,1,1 и 2,2,2,2 вполне возможно, что на принимающей стороне вы позвоните Receive три раза с 4-байтовым массивом и получите

  • 1,1,0,0 (Получить возвращенный 2)
  • 1,1,2,2 (Получить возвращенный 4)
  • 2,2,0,0 (Получить возвращенный 2)

Итак, что вам нужно сделать, это посмотреть на значения, которые вы получили Receive и продолжайте цикл, пока ваш массив байтов не заполнится.

byte[] TMP = new byte[4];

//loop till all 4 bytes are read
int offset = 0;
while(offset < TMP.Length)
{
    offset += serv.Receive(TMP, offset, TMP.Length - offset, SocketFlags.None);
}
TMP = new byte[BitConverter.ToInt32(TMP, 0)];

//I don't understand why you are doing this, it is not necessary.
serv.Send(new byte[1]); 

//Reset the offset then loop till TMP.Length bytes are read.
offset = 0;
while(offset < TMP.Length)
{
    offset += serv.Receive(TMP, offset, TMP.Length - offset, SocketFlags.None);
}

//I don't understand why you are doing this, it is not necessary.
serv.Send(new byte[1]);

return TMP;

Наконец, вы сказали, что «сетевой поток вас сбивает с толку». Я готов поспорить, что описанная выше проблема — одна из вещей, которые вас смутили, переход на более низкий уровень не устранит эти сложности.Если вы хотите, чтобы эти сложные части исчезли, чтобы вам не приходилось их обрабатывать, вам нужно будет использовать стороннюю библиотеку, которая обработает это за вас внутри библиотеки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top