>Также может быть такая ситуация что тебе придет пакет не полностью
у меня нет уверенности, как это работает в шарпе. я не знаю, что будет в твоем примере, если в датаграмме больше 256 байт, может быть, дойдет ее первая часть.
Ramm
> А конец пакета самому искать?
покажи как ты отправляешь данные.
Ramm
Отправляй в начале пакета данные о размере отправляемых данных.
Ramm
Из твоего кода:
if (UDP1.Available > 0) { while ( UDP1.Available > 0) { bytes = UDP1.ReceiveFrom( data, ref remoteIp); builder += Encoding.ASCII.GetString( data, 0, bytes); if ( builder.Length>=100) { break; } } }
Зачем тебе здесь первый if?
Ramm
UDP1.ReceiveFrom вернет тебе одну датаграмму. Если пришло две, вторая вернется при втором вызове UDP1.ReceiveFrom.
Ramm
> А как узнать где закончился один пакет и начался другой? Предположим, на один UDP-сокет пришло 2 пакета, один - 100 байт, другой 130 байт.
По UDP ты не можешь получать пакет частями, одной командой надо получать весь, предоставив буфер, в который влезет любой из твоих пакетов, с запасом. Реальную длину узнаешь вместе с комплектом полученных байт. Ты даже длину заранее запросить не можешь.
Первая же операция с пакетом просигнализирует системе что он обработан и она его удалит. Прочитаешь частично - остаток уже не получишь никак. Операция запроса длины пакета существует, но ее исполнение уничтожит сам пакет.
Каждая операция чтения выдает тебе ровно один пакет (дайтаграммами они называются), никак специально делить на пакеты по UDP не требуется.
Ramm
> Они никем, я так понял, дробиться не будут.
Будут они дробиться или не будут, на уровне сокетов тебя волновать не должно. Дробление - подробности доставки. Полезно знать что если не дойдет один фрагмент, система будет считать что не дошло ничего, и все дошедшее выкинет, в случае дробления. Тебе об этом не сообщит, не дойти имеет право. Это, на самом деле, практически не просаживает производительность из-за особенностей сетевых сбоев, которые совсем не случайные. Помехи в сети ходят пачками, то все доходит, то не доходит ничего, в течение какого-то времени. Когда пакеты выкидывают сервера, из-за перегрузки, эффект тот же самый, пропадает разом масса последовательно шедших пакетов.
s3dworld
> Зачем тебе здесь первый if?
Тут не нужен, я из кусочка своего кода этот выдернул... Там дальше был код, который отправлял ответное сообщение. Если на сокете что-то есть, то обработать, получить пакет и отправить ответ. Если ничего нет, то и заходить не надо.
kipar
> UDP1.ReceiveFrom вернет тебе одну датаграмму. Если пришло две, вторая вернется
> при втором вызове UDP1.ReceiveFrom.
Я МСДН посмотрел, почитал про этот ReceiveFrom, но там это как-то не очевидно написано. Я тоже так понял, что он за раз обработает только одну датаграмму.
Т.е. даже если data - это массив на 65000 байтов, то
bytes = UDP1.ReceiveFrom(data, ref remoteIp);
запихнет в нее только один пакет, даже если он 100-байтный, даже если на сокете висят еще 50 пакетов, а в bytes будет записан его размер.
Правильно я понял? -это главный вопрос...
Zab
> Прочитаешь частично - остаток уже не получишь никак.
Т.е. если я подставлю маленький буфер (массив), например 200, а пакет придет большего размера, например 500, то первые 200 байтов пакета в массив запишутся, остальные 300 пропадут и при слдующем вызове ReceiveFrom можно получить только новый пакет?
HolyDel
> покажи как ты отправляешь данные.
IPEndPoint remoteFullIp = remoteIp as IPEndPoint; string message = "*****"; data = Encoding.ASCII.GetBytes(message); EndPoint remotePoint = new IPEndPoint( remoteFullIp.Address, remoteFullIp.Port); UDP1.SendTo( data, remotePoint);
А еще вопрос, как долго данные будут висеть на сокете?
Zab
Т.е. вот тут говорят, что может большое сообщение (более 1400 байт) разбиться на несколько пакетов, часть пакетов потеряется, а я потом сам должен буду понять при считывании, что именно потерялось... Так вот это неправда?=)
Если пакеты потеряются, то все сообщение станет недоступным? Ситуация, когда мне отправляют одну строку типа "1234567890abcdefghij", (но побольше, предположим на 1500 знаков), а я считываю, и оказывается, что дошла только половина "abcdefghij" - исключена?
Если сообщение разбилось на пакеты благодаря MTU, то в случае пропажи одного пакета, все сообщение не доходит? Мне кажется это логичным, т.к. попробуй догадайся какая именно часть пропала, не помогут никакие вставки, флаги, строки, помечающие начало и конец. А если сообщение было зашифровано, так это вообще - мусор придет.
Ramm
> Правильно я понял? -это главный вопрос...
да.
собирается и разбирается оно на более низком уровне, это не твоя проблема, тебе придет столько сколько отправил или не придет вообще. Просто в целях оптимизации нет смысла делать большие посылки которые будут разбиваться превращаясь в ухудшенную версию tcp.
kipar
Спасибо огромное! Сейчас еще подожду, что Zab напишет, и все - бегом делать свой Телеграмм с Контрстрайком. Лопату для денег уже приготовил.
Татарин
> так что не парься и используй TCP, единственное проблема это то что если один
> пакет задержится то все пакеты замирают пока повторно тот не придет, в тестах (
> а я много тестил) это не бывают ни у кого
Татарин
> тут советы много кто давать любит но на практике те еще рукожопы
Татарин, судя по некоторым вещам, то ты и сам-то недалеко ушёл :-)
MixeYa
> Татарин, судя по некоторым вещам, то ты и сам-то недалеко ушёл :-)
по каким вещам?
> Во Flash тоже было только TCP (по крайней мере когда я его использовал). В то время UDP можно было использовать только в AIR.
Во Flash был RTMFP ещё.
Обновлено: о, сейчас глянул про него. Он основан на UDP, да. Но не уверен, что сохранил его преимущества/недостатки, а, т.к. давно на флеше не писал, не помню уже ничего.
Ramm
> Т.е. если я подставлю маленький буфер (массив), например 200, а пакет придет
> большего размера, например 500, то первые 200 байтов пакета в массив запишутся,
> остальные 300 пропадут и при слдующем вызове ReceiveFrom можно получить только
> новый пакет?
Да, это так.
Ramm
> Т.е. вот тут говорят, что может большое сообщение (более 1400 байт) разбиться
> на несколько пакетов, часть пакетов потеряется, а я потом сам должен буду
> понять при считывании, что именно потерялось... Так вот это неправда?=)
Если дробил не ты сам, отсылал единым пакетом, то и получишь ровно то, что посылал. Или не получишь вовсе.
Система может там внутри порезать еще, если ей так удобно, но ты работаешь как с не порезанными.
Сейчас не найдешь сетей, где максимальный размер пакета, на уровне сокетов, меньше 1200 байт (с каким-то там хвостиком, не помню цифру точно). До 1995 года можно было нарваться на более жесткие ограничения.
Пакет - слишком общий термин, он используется в протоколах разного уровня. Когда говорят о пакетах уровня сокетов UDP предпочитают их называть дейтаграмми.
Татарин
> по каким вещам?
Ну вот даже исходя из высказывания твоего. Смотри, ты человеку совет даёшь? Зачем?
Что ты тестировал?
Потери до 5% считаются нормой, даже на сегодняшний день.
Но ведь есть ещё мобилки, мобилки в метро, мобилки за городом, ещё спутники, один чувак сказал, что даже диал-апы до сих пор используют.
Так что, называть форумчан рукожопами, с твоей стороны, на мой взгляд не к месту, по причине, которую я озвучил выше.
Покопался тут про ограничения...
Длина 508 байт - ограничение RFC, более жесткие ограничения не имеет права ставить никто, если хочет работать в рамках интернета.
Пакеты длиной до 1432 как правило не дробятся при пересылке по локальной сети Ethernet. Локальная сеть в цепи доставки конечно обычно присутствует, но кто сказал, что она в ней главная? И кто сказал, что она вообще будет, а если будет, то стандарта Ethernet?
Упоминается что где-то могут не поддерживать доставку фрагментированных пакетов. Такое действительное есть? Или это отголоски страхов начала 90х? Сетей тех времен давно уже не существует физически, а если кто их в музее и найдет, вполне нормально отказаться с ними работать.
Тема в архиве.