Почему сервер не получает все пакеты UDP при локальной передаче с использованием сокетов в C #?

У меня есть сервер и клиентское приложение, в котором клиент отправляет на сервер кучу пакетов. Используемый протокол - UDP. Клиентское приложение порождает новый поток для циклической отправки пакетов. Серверное приложение также создает новый поток для ожидания пакетов в цикле.

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

private void EVENTHANDLER_UpdateTransferProgress(long transferedBytes) {
    receivedBytesCount += transferedBytes;
    packetCount++;
}

Таймер в каждом приложении будет обновлять пользовательский интерфейс с учетом последней информации от receivedBytesCount и packetCount.

У клиентского приложения вообще нет проблем, вроде все работает должным образом, а пользовательский интерфейс правильно обновляется каждый раз при отправке пакета. Сервер проблемный ...

Когда передача завершена, receivedBytesCount и packetCount не будут соответствовать ни общему размеру в отправленных байтах, ни количеству пакетов, отправленных клиентом. Кстати, каждый пакет имеет размер 512 байт. Серверное приложение считает пакеты, полученные сразу после возврата вызова от Socket.ReceiveFrom(). И кажется, что по какой-то причине получает не все пакеты, которые надо.

Я знаю, что я использую UDP, который не гарантирует, что пакеты действительно прибудут в пункт назначения, и повторная передача не будет выполняться, поэтому может быть некоторая потеря пакетов. Но у меня вопрос: поскольку я фактически тестирую это локально, сервер / клиент находятся на одном компьютере, почему именно это происходит?

Если я помещаю Thread.Sleep(1) (что, кажется, переводится как пауза в 15 мс) в цикл отправки клиента, сервер получит все пакеты. Поскольку я делаю это локально, клиент отправляет пакеты так быстро (без вызова Sleep()), что сервер не успевает за ними. Это проблема или может быть где-то еще?


person rfgamaral    schedule 10.04.2012    source источник
comment
Я думаю, вы можете использовать wirehark, чтобы проверить, не потеряна ли посылка   -  person llj098    schedule 10.04.2012
comment
Я бы попытался установить для ReceiveBufferSize большее значение, например 256 КБ (по умолчанию 8 КБ).   -  person L.B    schedule 10.04.2012
comment
@ L.B Я не могу этого сделать, они должны быть 512 байт. Но я не пытаюсь решить потерю пакетов, я пытаюсь понять это.   -  person rfgamaral    schedule 10.04.2012
comment
установка ReceiveBufferSize не изменит логику вашей программы. Вы можете продолжать отправлять или получать пакеты размером 512 байт. это опция UdpClient (или сокета)   -  person L.B    schedule 10.04.2012
comment
@ L.B Извините, я неправильно понял ... Кажется, это устранило проблему. Но в документации говорится: подумайте об увеличении размера буфера, если вы передаете большие файлы или используете соединение с высокой пропускной способностью и высокой задержкой, и, поскольку я делаю это локально, имеет смысл увеличить. Но если я делаю это по сети (широкой или локальной), следует ли мне немного уменьшить его или можно оставить 256 КБ?   -  person rfgamaral    schedule 10.04.2012
comment
Извините, не знаю. Лучший способ - это проверить и увидеть.   -  person L.B    schedule 10.04.2012
comment
@ L.B На самом деле, изменение размера буфера, похоже, не решило проблему полностью. После еще нескольких тестов я понял, что потери пакетов случаются реже. В большинстве случаев сервер получает все пакеты, но иногда этого не происходит. Если я увеличу буфер до большего размера, это может решить проблему. Но мой первоначальный вопрос остается. Я ищу техническое объяснение, почему пакеты теряются ...   -  person rfgamaral    schedule 10.04.2012
comment
Это потому, что я использую UPD и передача слишком быстрая, сервер не может справиться с такой скоростью и не улавливает все пакеты?   -  person rfgamaral    schedule 10.04.2012
comment
Думаю, да, некоторое время назад у меня была такая же проблема, и я увеличивал размер буфера до тех пор, пока не казалось решающим проблему. В моем случае это было 256 КБ. Я знаю, что это не настоящий ответ, но, по крайней мере, решение. Более сложным способом было бы добавить порядковые номера и ретрансляции к вашему протоколу.   -  person L.B    schedule 10.04.2012


Ответы (1)


`` Если я помещу Thread.Sleep (1) (который, кажется, преобразуется в паузу в 15 мс) в цикле отправки клиента, сервер получит все пакеты ''

Буферы сокета заполняются, и стек отбрасывает сообщения. UDP не имеет управления потоком, поэтому, если вы попытаетесь отправить огромное количество датаграмм в жестком цикле, некоторые из них будут отброшены.

Используйте свой цикл sleep () (тьфу!), Реализуйте некоторую форму управления потоком поверх UDP, реализуйте некоторую форму несетевого управления потоком (например, используя асинхронные вызовы, буферные пулы и межпотоковую связь) , или используйте другой протокол со встроенным управлением потоком.

Если вы выгружаете материал в сетевой стек быстрее, чем он может его переварить, вы не должны удивляться, если он время от времени вырывается.

person Martin James    schedule 10.04.2012
comment
Я тоже должен заниматься управлением потоком, но этот вопрос не касался решения проблемы потери пакетов. Извините, если я не совсем понял это. Но ваш первый абзац (не считая цитаты) ответил на мой вопрос. :) - person rfgamaral; 10.04.2012