.NET Socket.BeginReceive: когда вызывается обратный вызов
Мне было интересно, когда обратный вызов, который предоставляется с помощью вызова BeginRecieve, запускается.
- Это когда он получил столько данных, сколько может вместить буфер? И если так - что делать, если данные меньше, чем буфер)
- Это когда он получил один пакет TCP/IP?
- Это что-то еще?
Я нашел похожий вопрос, который я повторю, так как не могу выразиться намного яснее:
Теперь во всей документации говорится, что обратный вызов, как указано в BeginReceive, вызывается, как только "данные получены". Но это довольно расплывчато: когда наступит именно этот момент, если вы не знаете, как именно этот процесс предоставляет данные?
Одним из критериев является то, что BeginReceive() считается завершенным (и, таким образом, вызывается callbask), когда буфер в объекте состояния заполняется до указанного размера буфера. Но что, если процесс "доставки" подает данные в неизвестных количествах и нерегулярно? Например, если он сначала доставляет 100 байтов подряд, а затем существует интервал времени в 1 миллисекунду, а затем следуют еще 200 байтов: завершает ли BeginReceive 100 байтов входящих данных? Или 300?
http://www.pcreview.co.uk/forums/exactly-beginreceive-socket-considered-completed-t2899270.html
2 ответа
По моему опыту, он вызывается для любых данных, доступных без задержки. Это означает, что чтение может быть довольно маленьким, например, 1400 байт или около того, потому что это порядка размера MTU.
Чтения могут быть кратны этому, потому что, если пакеты поступают не по порядку, все они становятся видимыми для приложения в момент поступления логически первого из них. В этом случае вы можете одновременно читать все смежные пакеты в очереди.
Я полагаю, что ваш размер чтения увеличится на очень быстрых соединениях, потому что ваше приложение может не обрабатывать байты так быстро, как сеть доставляет отдельные пакеты.
Sidenote: обратный вызов BeginReceive вызывается точно в тот же момент, когда возвращался бы запрос. Вы не можете уменьшить задержку таким образом. (Задержка на самом деле возрастет незначительно, потому что асинхронные операции могут иметь больше накладных расходов, чем блокирующие).
Предполагая, что ваш сокет является сокетом TCP. Затем обратный вызов запускается, когда доступны какие-либо данные, но он доставляет в обратном вызове максимально возможный размер буфера. В любом случае вам нужен протокол кадрирования (означает, что вам нужно несколько раз вызвать BeginReceive(..) и обнаружить и собрать отправленные кадры).