Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Странно  (Прочитано 25192 раз)
0 Пользователей и 1 Гость смотрят эту тему.
alteest
Гость
« : 23-06-2003 10:29 » 

вопрос такой:
клиент-сервер, работтают и пр. в один момент сервер начинает отправлять клиенту данные. длина 40. клиент их получает и все вроде бы нормально. НО один из блоков клиент получает как 2 по 20!!!
в принципе проблема не критическая - но все же где тут грабли?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 23-06-2003 14:31 » 

Цитата: alteest
вопрос такой:
клиент-сервер, работтают и пр. в один момент сервер начинает отправлять клиенту данные. длина 40. клиент их получает и все вроде бы нормально. НО один из блоков клиент получает как 2 по 20!!!
в принципе проблема не критическая - но все же где тут грабли?


Для потоковых соединений это вполне допустимо и стоит это учитывать.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
alteest
Гость
« Ответ #2 : 24-06-2003 09:20 » 

т.е. я могу отправлять любые сообщения - любой длины, а они будут приходить как бог на душу положит?
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #3 : 24-06-2003 12:04 » 

В зависисмоти от сети.
Существует размер пакета который в сети максимальный.
Записан

А птичку нашу прошу не обижать!!!
Olej
Гость
« Ответ #4 : 24-06-2003 16:00 » 

Цитата: alteest
т.е. я могу отправлять любые сообщения - любой длины, а они будут приходить как бог на душу положит?


Естественно Ага...
В TCP нет "пакетов", "сообщений" etc. - это всё осталось на уровне UDP - есть только "поток" (или потоки: передаваемый и принимаемый). К этому нужно привыкнуть ... и всё становится намного проще...

Размеры же "порций", которые "проталкиваются" в TCP за один раз - зависят от текущих размеров окна передачи и окна приёма (их размеры сообщающиеся TCP стороны каждый раз координируют). Вообще, алгоритм изменения размеров окон - достаточно сложный ("медленный старт", "отсроченные подтверждения" ... etc. - разные механизмы влияют). Но, в правильно спроектированных net-приложениях, эти размеры не должны никак фигурировать и оказывать влияния.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #5 : 24-06-2003 16:03 » 

Нет - Олег - мне кажется ты не прав - любой снифер показывает IP пакеты.
А протокол передачи именно TCP/IP  Ага
Есть MTU по моему так это называется где мы утанавлмваем зависимость велична пакета от скорости сети или что-то в этом роде.
Я просто счас этим уже около года не занимался, вот и названия подзабыл.
Записан

А птичку нашу прошу не обижать!!!
Lex
Специалист

ru
Offline Offline

WWW
« Ответ #6 : 24-06-2003 16:13 » 

Так это IP пакет, в TCP. который идет поверх IP пакетов(для приложения) уже нет, есть только поток данных, как сказал Олег.
Записан

Megabyte be with you!
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #7 : 24-06-2003 16:28 » 

Это когда они уже в приложении...
Хотя разговор идет о приложении, но из-за разбиения внутри мелддленных сетей, могут приходить и разбитыми.

Кстати еще вот вспомнил, многое зависит и от того по какому пути идет пакет.
Если в дороге ему будет всречен некий участок, который будет загружен, то пакет IP будет разбит раутером и часть вполне может уйти к следующему раутеру совершенно другим путем, и приехать позже.

Но это в апликации уже не видно - лирика... Отлично
Записан

А птичку нашу прошу не обижать!!!
Olej
Гость
« Ответ #8 : 24-06-2003 16:33 » 

Цитата: Гром
Нет - Олег - мне кажется ты не прав - любой снифер показывает IP пакеты.
А протокол передачи именно TCP/IP  Ага
Есть MTU по моему так это называется где мы утанавлмваем зависимость велична пакета от скорости сети или что-то в этом роде.
Я просто счас этим уже около года не занимался, вот и названия подзабыл.


Нет, всё правильно - это всё абстракции разных уровней:

- MTU - это относится к MAC (канальному) уровню - это физические пакеты, циркулирующие в среде...;
- IP - пакеты - это транспортный уровень...;
- TCP/UDP - это абстракции более высокого уровня (я здесь специально не хочу привязываться к 7-ми уровневой модели ISO, т.к. TCP/IP не соответствует ей полностью ... но это "беда" не TCP/IP, а модели ISO).

Вот смотрите: тот-же UDP - здесь "сообщения", "пакеты" - но это вовсе не значит, что 1 пакет UDP соответствует 1-му пакету IP - он может быть и сегментирован, и сильно ... но это - "пакет". Любой снифер будет видеть N-пакетов IP (и он - прав!), но это - только один(!) пакет UDP, и стек IP передаст пользователю этот 1 пакет только тогда, когда придут все N IP-пакетов, и в стеке (!) будет собран (дефрагментирован) пакет UDP.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #9 : 24-06-2003 16:36 » 

Правильно, но все равно тогда не понятно откуда взялись те самые 20+20 = 2 пакета вместо одного, кстати и как это было определено....alteest скажи как ты опрределил , что пришло 2 пакета?
При чтении из сокета ты запрашиваешь сколько  :?:
Записан

А птичку нашу прошу не обижать!!!
Olej
Гость
« Ответ #10 : 24-06-2003 19:44 » 

Цитата: Гром
Правильно, но все равно тогда не понятно откуда взялись те самые 20+20 = 2 пакета вместо одного,


Например:
- отсылается в поток 40 байт;
- окно приёма в это время равно 20 байт;
- 20 байт отсылаются приёмной стороне;
- read( ... 40 ... ) - читает 20 байт, имеющиеся у стека TCP/IP и возвращает значение20...
- после этого чтения с пакетом ACK TCP приёмник отсылает новое значение окна приёма ... оно может стать и 200...
- передающая сторона тут-же отсылает оставшиеся 20 байт...
- приёмная - принимает 20 байт...
Всё нормально: идёт передача данных ЧЕРЕЗ ПОТОК.
Что бы постоянно не сбиваться при TCP - нужно забыть что такое "пакет", "порция" и т.д. ... это - ТРУБА через которую качаются байты ... а кто там и как крутит вентиль на этой трубе (а крутит - правила TCP!) так это нас не должно касаться.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #11 : 24-06-2003 19:54 » 

Возможно....возможно.
Записан

А птичку нашу прошу не обижать!!!
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 25-06-2003 03:22 » 

Ну вот, вроде, с теорией разобрались...
Только не понятно - как надо извратиться чтобы получать всего по 20 байт за раз?  Я шокирован!
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #13 : 25-06-2003 03:30 » 

Улыбаюсь ну коммандные пакеты в моем протоколе были и по 4 байта "HELO" например Улыбаюсь
Записан

А птичку нашу прошу не обижать!!!
alteest
Гость
« Ответ #14 : 25-06-2003 10:31 » 

так еще раз говорю - сервак ооттсылает пакеты по 40 байт!!!!!! их идет определенное количество. клиент все пакеты получает нормально кроме одного (это не пепрвый и не последний пакет - где-то в средине). Определяю что 2 по 20 - лог смотрю, да и слиетн эти пакеты куда надо пишет, а там небольшие грабельки из-за этого получаются.
Записан
Olej
Гость
« Ответ #15 : 25-06-2003 15:24 » 

Цитата: RXL
Ну вот, вроде, с теорией разобрались...
Только не понятно - как надо извратиться чтобы получать всего по 20 байт за раз?  Я шокирован!


Обратите внимание: большинство (все!) сервисов TCP UNIX используют текстовое содержимое (формат) данных, с разбиением на строки, а окончание запроса - 2 конца строки подряд!

Это не случайно - в TCP потоке лучше всего синхронизацию данных лучше всего делать по их содержимому.
Записан
Olej
Гость
« Ответ #16 : 25-06-2003 15:30 » 

Цитата: alteest
так еще раз говорю - сервак ооттсылает пакеты по 40 байт!!!!!! их идет определенное количество. клиент все пакеты получает нормально кроме одного (это не пепрвый и не последний пакет - где-то в средине). Определяю что 2 по 20 - лог смотрю, да и слиетн эти пакеты куда надо пишет, а там небольшие грабельки из-за этого получаются.


"так ещё раз говорю" ... в TCP нет пакетов, и то, что "сервак ооттсылает пакеты по 40 байт!!!!!!" - это ВАМ кажется, что он отсылает, это ВЫ write() написали и успокоились.

Соединение TCP (стек TCP/IP) имеет право отсылать из передаваемых вами write() байт столько - сколько ОН САМ сочтёт целесообразным!
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #17 : 25-06-2003 15:34 » 

Да и кстати - написать цикл приема всех нужных байт, а не ориентироваться на принятые один раз - ИМХО дело 2 секунд.
Записан

А птичку нашу прошу не обижать!!!
Olej
Гость
« Ответ #18 : 25-06-2003 22:42 » 

Цитата: Гром
Да и кстати - написать цикл приема всех нужных байт, а не ориентироваться на принятые один раз - ИМХО дело 2 секунд.

Да, вот я к этому всё и веду... Только, вы должны знать:
- сколько байт у вас будет ссобщение;
... или ещё лучше:
- использовать ограничитель тела сообщения (а ещё точнее - "разделитель").
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #19 : 25-06-2003 23:36 » 

На крайняк CRC простейшее... Ага
Записан

А птичку нашу прошу не обижать!!!
alteest
Гость
« Ответ #20 : 26-06-2003 10:20 » 

Цитата: Гром
Да и кстати - написать цикл приема всех нужных байт, а не ориентироваться на принятые один раз - ИМХО дело 2 секунд.


дык, я это уже сделал. ладно - согласен, что написав "сервак отправляет пакеты" - я дал маху.
но я спрашивал. "Почему клиент читает ввсего 20 байт, когда я ему говорю - читать 40?". и никакие маршрутизаторы - тут не при чем, потому что проверял на vmware - все на одной маашине, просто сервак пашет под одной ОС, клиент - под другой. и баг вылазит, постоянно?! (клиент кстати - виндузный)
Записан
sss
Специалист

ru
Offline Offline

« Ответ #21 : 04-07-2003 04:49 » 

Попробуй проверить буфер который отправляешь. Там может быть такое, что поделит его (например /0). А вообще еще можно поэксперементировать с задержкой на чтение сетевого стека (потоковый не так ли ?) он  :!: должен СКЛЕЕВАТЬСЯ.
Записан

while (8==8)
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #22 : 06-08-2003 22:04 » 

Цитата

"Почему клиент читает ввсего 20 байт, когда я ему говорю - читать 40?".


клиент читает ровно столько, сколько есть во входном буфере TCP и соответственно если он читает 20 байтов, то во входном буфере находится 20 байтов, а теперь почему там 20 байтов, а не 40. Как совершенно верно заметил Olej

Цитата

"так ещё раз говорю" ... в TCP нет пакетов, и то, что "сервак ооттсылает пакеты по 40 байт!!!!!!" - это ВАМ кажется, что он отсылает, это ВЫ write() написали и успокоились.

Соединение TCP (стек TCP/IP) имеет право отсылать из передаваемых вами write() байт столько - сколько ОН САМ сочтёт целесообразным!


если функция write вернула 40 это не значит что было отправлено 40 байт данных (TCP может задержать отправку данных на какое-то время => привыходе из write может получиться, что не отправлено ни байта!!! , а может быть отправлено например 20 байтов, а спустя какое-то время остальные 20, между прочим TCP мог ды вообще доставить вам данные ПОБАЙТНО т.е. при вызове recv(...40...) на клиенте вы бы считывали ОДИН!!! байт и это корректная работа TCP)

А если при приеме данных вы хотите считывать 40 байтов то энто делается так

Socket socket;
int flags;

int length = 40; // но это не обязательно
int success_recv = 0;
int result = 0;
char * buffer = new char[length]; // не хорошо но для примера сойдет

while (need_recv < length)
{
    result = recv(socket, buffer + success_recv, length - success_recv, flags);

    //..... обработка ошибок
    success_recv += result;
}

//  используем buffer

delete []buffer;

И это все как уже говорилось надо делать в отдельном потоке (потому как сокет блокирующий)
Записан

С уважением Lapulya
Asan
Гость
« Ответ #23 : 07-08-2003 12:49 » new

Вообще-то, функция write (или send) просто помещает переданые ей для отпраки данные во внутренний буфер TCP и сразу возвращает управление. Что дальше будет с этими данными - это уже задача TCP.
Тоже самое и read (recv) - если есть, что читать из буфера, она читает, что там есть. И не значит, что если ты сказал recv(sock, buffer, 100, ..),
она тебе прочитает 100 байт. Сколько есть, столько и прочитает. От этого и надо плясать.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines