Разбиение пакетов TCP
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.123] |
|
|
Соблюдайте общие правила форума
MSDN Library
FAQ раздела
Поиск по разделу
Как правильно задавать вопросы| Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Разбиение пакетов TCP
|
Сообщ.
#1
,
|
|
|
|
Добрый день!
Использую связку TServer\ClientSocket (дефолтные из D2007) в неблокирующем режиме. Я подразумеваю, что инфа, отправленная одним вызовом sendText на одной из сторон, придёт полностью в буфере первого сработавшего onRead на противоположной стороне. Правильно ли такое предположение? |
|
Сообщ.
#2
,
|
|
|
|
Не совсем.
Дело в том, что в TCP/UDP существует такое понятие как low water-mark Сокет готов для чтения, если выполнено одно из следующих условий: • Число байтов данных в приемном буфере сокета больше или равно текущему значению минимального количества данных low water-mark (может быть задано функцией setsockopt() с помощью опции сокета SO_RCVLOWAT) для приемного буфера сокета. Для сокетов TCP и UDP значение low water-mark по умолчанию равно 1. Грубо говоря, как только в буфер сокет придет ОДИН байт - выставится событие FD_READ PS Кстати, ПАКЕТОВ в TCP нет. Порции данных, формируемые модулем ТСР, носят название "сегмент" |
|
Сообщ.
#3
,
|
|
|
|
unconnected
сетевые vcl компоненты без понимания протоколов - зло! Под борландом/эмбаркадеро лучше всего работать либо напрямую с асинхронными сокетами, либо пользовать дот нет. Первое дает возможность реализовать то, что ты хочешь, достаточно эффективно. Второе - быстро. Ну и да, тебе нужно поверх твоих инкубаторских компонентов обозначать неким маркером начало и конец передачи, ибо тцп сокет - он просто дает тебе поток где ты можешь отправлять байты хоть по пять-десять и получать сотнями или тысячами и наоборот, поэтому для тсокетклиентов и прочего мусора - нет как такового события onRead. Теоретически, ты можешь отправить сотню байт одним send и получить 99 событий onRead, вычитывая по одному байту. Твоя проблема - типичная для новичков, запустивших дэлфи и думающих, что там в стандартных компонентах все есть и ничего не надо делать. Но на этапе реализации сетевых протоколов всех юзеров ожидает "облом петрович" - всю эту палитру vlc, на которую так все уповают, нужно выбросить. И делать все по уму (хотя "Винда" и "по уму" понятия из разных галактик). Т.е. Если ты хочешь отправить текст и получить текст - тебе нужно перебираться протоколом повыше (почитай о семиуровневой модели https://ru.wikipedia.org/wiki/%D0%A1%D0%B5%...D0%BB%D1%8C_OSI) - работать не на уровне TCP (третий, он же транспортный), а уже на уровне четвертом, он же уровень приложений, скажем, по HTTP. Ну или как вариант, напиши свой протокол, где у тебя будет обозначено начало передачи, конец передачи, и для своего протокола создай визуальную компоненту и поделись ею со всеми на форуме ))))) |
|
Сообщ.
#4
,
|
|
|
|
Цитата nemez @ 1.поэтому для тсокетклиентов и прочего мусора - нет как такового события onRead. 2.Теоретически, ты можешь отправить сотню байт одним send и получить 99 событий onRead, вычитывая по одному байту. Первое противоречит второму и наоборот. |
|
Сообщ.
#5
,
|
|
|
|
Цитата Oleg2004 @ имеется ввиду к пониманию автором самого события onRead, а именно Цитата Я подразумеваю, что инфа, отправленная одним вызовом sendText на одной из сторон, придёт полностью в буфере первого сработавшего onRead на противоположной стороне. поэтому еще раз акцентирую внимание - предположение неправильное, ибо инфа, отправленная одним вызовом sendText, может вызвать несколько вызовов onRead, и наоборот, можно несколько раз вызвать sendText, и получить одно событие onRead. onRead - не обязательно получение буфера, отправленного одним send, но получение либо фрагментов из одного send, либо вообще склейки буферов, отправленного несколькими send, либо если повезет, то можно и получить буфер отправленный send. Поток, он и в Африке поток. TCP дает именно поток, но оно него не контролирует и не должно. Поток контролируют на уровень выше. |
|
Сообщ.
#6
,
|
|
|
|
Цитата nemez @ поэтому еще раз акцентирую внимание - предположение неправильное, ибо инфа, отправленная одним вызовом sendText, может вызвать несколько вызовов onRead, и наоборот, можно несколько раз вызвать sendText, и получить одно событие onRead. onRead - не обязательно получение буфера, отправленного одним send, но получение либо фрагментов из одного send, либо вообще склейки буферов, отправленного несколькими send, либо если повезет, то можно и получить буфер отправленный send. Безусловно поток читать можно и по байтику, и сотнями... Но событие на сокете, фиксирующее прибытие low water-mark значения, всегда возникает в модулях TCP/UDP, во всех операционках - типа FD_READ. А уж сколько раз оно еще может возникнуть...так это дело пятое... А в остальном согласен... |
|
Сообщ.
#7
,
|
|
|
|
ключевое слово -
Цитата во всех операционках винду нельзя рассматривать как полноценную ось, это скорей недооперационка с недоFD_READ. взято здесь: https://msdn.microsoft.com/en-us/library/wi...v=vs.85%29.aspx Цитата SO_RCVLOWAT A socket option from BSD UNIX included for backward compatibility. This option sets the minimum number of bytes to process for socket input operations. This option is not supported by the Windows TCP/IP provider. Как видим по тексту, оно в винде болтается только для обратной совместимости с BSD UNIX, на самом деле оно для мебели и и в реалиях не работает. Об этом утверждают сами мелкомягкие. К ним, на самом деле, особых претензий нет. Но это уже сути вопроса касается не напрямую. |
|
Сообщ.
#8
,
|
|
|
|
Цитата nemez @ Как видим по тексту, оно в винде болтается только для обратной совместимости с BSD UNIX, на самом деле оно для мебели и и в реалиях не работает. Ну как тут не согласиться... К сожалению, некоторые фичи сетевого программирования, доступные в *nix, для винды все еще экзотика. Да, опция может и не поддерживаться, но само дефолтное значение в 1 байт - оно таки есть. И как только карточка перешлет в буфер приема сокета 1 байт, событие FD_READ взведется. |
|
Сообщ.
#9
,
|
|
|
|
Если передача не блокируемая, то передача идёт потоком и о пакетах можно забыть. Блокировка как раз и синхранизирует принятие пакета.
А про low water-mark можете забыть это устаревшая технология. Так как большенство устройств работают пакетами или блоками, а не побайтно. Так быстрее. На микро-контроллёре это ещё рентабельно. Некоторые никсы её тоже эмулируют для совместимости. |
|
Сообщ.
#10
,
|
|
|
|
Цитата Pavia @ А про low water-mark можете забыть это устаревшая технология. Так как большенство устройств работают пакетами или блоками, а не побайтно. Интересное заявление. С каких таких пор протокол ТСР стал устаревшей технологией??? И куда подевался его таймер запросов (persistence timer), описанный в спецификации протокола? Цитата Пусть получатель, приостановивший передачу данных путем посылки сегмента с нулевым размером окна, отправляет своему партнеру сообщение о возобновлении работы, но тот его не получает. Если подтверждения теряются, то это в принципе может привести к тупиковой ситуации, когда обе стороны будут дожидаться прихода подтверждений. В таком случае, чтобы продолжить передачу, отправитель с периодом, задаваемым таймером, посылает запросы с одним байтом данных. Именно для этого и установлен low water-mark равный одному байту... А блоки-пакеты на устройствах - протокол не волнуют... |
|
Сообщ.
#11
,
|
|
|
|
Цитата С каких таких пор протокол ТСР стал устаревшей технологией??? ну так протокол старый, как дерьмо мамонта. Правильно его называют, time consumption protocol. Он разрабатывался десятки лет назад, когда сеть была коаксиальной, и любая непонятка для него - congestion. Дрочилово с размером окна, которое работает непойми как и кем и когда реализованное. Он реально устарел и фактически не работает по человечески ни на беспроводных каналах, ни на линиях связи между континентами; Парк этих древних протоколов пора менять. Они не удовлетворяют коммуникационным возможностям на сегодняшний день. |
|
Сообщ.
#12
,
|
|
|
|
Цитата nemez @ ну так протокол старый, как дерьмо мамонта. Ну да, таблице умножения лет наверно так тысяч пять...дерьмо мамонта. Цитата nemez @ Он разрабатывался десятки лет назад, когда сеть была коаксиальной, и любая непонятка для него - congestion. Дрочилово с размером окна, которое работает непойми как и кем и когда реализованное. Он реально устарел и фактически не работает по человечески ни на беспроводных каналах, ни на линиях связи между континентами; К сетевому и канальному уровням транспортник ТСР не имеет никакого отношения. Да, протокол старый - но работает до сих пор однозначно эффективно - единственный протокол, в котором внутри реализован механизм 100% гарантии передачи. Так что альтернативы просто нет. И не будет я думаю еще лет 100 .А механизм скользящего окна - просто люкс... Единственный протокол, в котором внутри реализован механизм регулирования скорости передачи. Имхо... |
|
Сообщ.
#13
,
|
|
|
|
Цитата Oleg2004 @ В таком случае, чтобы продолжить передачу, отправитель с периодом, задаваемым таймером, посылает запросы с одним байтом данных. В RFC такого нет. Там написано что с приходом первого байта возобновляется передача. А это может быть и байт и пакет. Грубо говоря достаточно проверки вида Length >0. Но линуксойды ввели порог. Понятно что в какой-то реализации это имеет смысл. Но гораздо лучше делать это пакетами. Добавлено http://pubs.opengroup.org/onlinepubs/79087...setsockopt.html Цитата SO_RCVLOWAT Sets the minimum number of bytes to process for socket input operations. The default value for SO_RCVLOWAT is 1. If SO_RCVLOWAT is set to a larger value, blocking receive calls normally wait until they have received the smaller of the low water mark value or the requested amount. (They may return less than the low water mark if an error occurs, a signal is caught, or the type of data next in the receive queue is different than that returned, e.g. out of band data). This option takes an int value. Note that not all implementations allow this option to be set. |
|
Сообщ.
#14
,
|
|
|
|
А я-то раньше полагался на один пакет (отправка) <=> один onRead, пока в логах не увидел страанное деело..
Сделал деление на пакеты на уровне своих данных. Ещё, наверное, хорошо было бы нумеровать их, ведь гарантии порядка прихода вроде как тоже нет. |
|
Сообщ.
#15
,
|
|
|
|
Цитата Олег2004 @ однозначно эффективно - единственный протокол, в котором внутри реализован механизм 100% гарантии передачи. не единственный, существует целый ворох таковых на базе УДП, УДТ например. Там тоже гарантирована 100% доставка. Тот же тфтп и иже с ним, поэтому говорить о том, что этот протокол единственный, не приходится. Об эффективности ТСР - отдельная песня. Из которой слов не выкинешь Добавлено Цитата Oleg2004 @ И не будет я думаю еще лет 100 . А механизм скользящего окна - просто люкс... Единственный протокол, в котором внутри реализован механизм регулирования скорости передачи. Механизм скользящего окна - с архитектурной точки зрения хорош и на сегодня применяется не только в TCP. Механизм регулирования скорости передачи - это тупо тормоз для передачи, и в случае непонятки или потери он становится. Тупо становится, с последующими перерукопожатиями, потом опять начинает тошнотворно увеличивать размер окна, постепенно разгоняясь. Механизм адаптации к параметрам канала, мягко говоря отстойный, тупой и неэффективный. На сегодняшний день есть коммерческие реализации сетевых протоколов, позволяющие работать более эффективно по сравнению с TCP. Специально для беспроводных сетей, вайфаев, лте, работающих с джиттером, задержкой и потерями. Хочешь хорошую передачу даты - плати. Или юзай дедушку TCP. |