| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > Сокеты Беркли, recv |
| Автор: mad_lollipop 16.11.2008, 15:13 |
| Недавно начал работать с сокетами, использую их в чистом виде, т.е. Сокеты Беркли+AF_INET, SOCK_STREAM, IPPROTO_TCP, потоковые, TCP. Возник вопрос, связанный с функцией recv. Если наш сокет не асинхронный, тогда при вызове этой функции мы ждем, пока во входном буфере сокета не появятся данные присланного пакета. При появлении данных в буфере мы можем обрабатывать полученное. Но вот что интересует больше всего: гарантируется ли полнота присланных данных, т.е. если нам послали 50 байт, то нам их столько и прийдет, или может возникнуть ситуация, когда нам эти 50 байт придут по частям, причем после получения первой части байтов наша программа получит возможность работы не дожидаясь получения следующих частей??? Возможно, все это реализуется на уровне TCP? Или как? |
| Автор: jonie 16.11.2008, 18:28 |
| описанная ситуация вполне возможна, и зависит не только от настроек ОС, но и от устройства стека TCP\IP в системе... а почему это вам должны давать сразу все присланные данные? может их там будет 20 мегабайт... |
| Автор: J0ker 16.11.2008, 19:47 |
| для UDP пакет приходит целиком, если на recv запрошено меньше, то остаток теряется для TCP возможна фрагментация пакетов (т.к. фактически пакетов нет - это потоковый протокол), при этом данный не теряются, даже когда в recv запрошено меньше имеющегося |
| Автор: SVN74 17.11.2008, 00:20 | ||
| Я был столкнулся с подобной проблемой при пересылке больших размеров данных (в МАССИВАХ), так как массив надо заполнить за один присест, пришлось смастерить свою функцию для полного заполнения массива: Где: RecivedData - Массив данных SizeOfData - Размер массива SizeDataForSpeed - Можно устанавливать любую скорость но не больше размера массива ///////////////////////////////////////////////////////////
Да... При ошибках будет возвращать -1 |
| Автор: jonie 19.11.2008, 01:22 | ||||
| вспоминается тот незабываемый код, что когда-то писал наш офис в тайланде.... опишу пошагово (без обид, с юмором):
|
| Автор: SVN74 19.11.2008, 23:34 | ||||||||||
Ну во первых чтобы использовать эту функцию буфер "RecivedData" заранее должен быть проверен и подготовлен
Как ни странно на скорость влияет ...
Признаю... Лишнее... Можно вычеркнуть.
Здесь Ptr изначально void* - приводить не обязательно, иначе была бы ошибка, (проверено).
..................................................................................................................... Несмотря на насмешки, этот код критических ошибок не имеет, конечно эго можно упростить вообще. У меня эта функция скачивает сотнями Ггб в сети и ошибок не возникало, даже когда я ее принудительно садил на ошибки. ..................................................................................................................... Что интересно, как только кто ни будь просит помощи в написании кода - помогать никто практически не хочет, тут я поддерживаю людей, которые помогают, тратя свое время... Но вот (блеснуть своим умом) обсудить чужой код , пускай не доскональный желающих довольно много, что интересно это чаще относится к людям у кого сообщений переваливает за 1000 - такой народ обычно ничего своего не выставляет... БЕЗ ОБИД |
| Автор: REZiaMIX 19.11.2008, 23:43 | ||
Не в тему но: Поддерживаю! |
| Автор: vinick 20.11.2008, 00:40 | ||||||
У тебя исключения бросает только new. Так что никакой очистки не надо.
А теперь представь ситуацию SizeOfData=100, SizeDataForSpeed = 40 и у тебя recv 3 раза подряд прочитает по 40 байт. Потеря 20 байт и выход за границы массива в твоём приложении не критично ;) Влияет, но очень опосредовано. |
| Автор: jonie 20.11.2008, 00:58 | ||||||||||
Добавлено через 3 минуты и 3 секунды
|
| Автор: SVN74 20.11.2008, 20:35 | ||
| С учетом выше сказанных замечаний упростил свою функцию. Работает также без проблем. Какие замечания будут?
|
| Автор: J0ker 20.11.2008, 21:05 |
| о а теперь как мы отличим - сокет закрывают или у нас ошибка? |
| Автор: SVN74 20.11.2008, 21:27 |
Ну на практике идет поток (бесконечный) и эта функция получает определенный размер данных, если поток завершится раньше, то сработает ошибка на “ресиве” и возвращается -1. Ну конечно передающий код не должен быть с перерывами, так как будет ожидание пока не дойдут все данные... |
| Автор: J0ker 20.11.2008, 21:49 |
| вы меня не поняли как определить - сокет закрыли с той стороны или у нас чего-то сломалось? |
| Автор: SVN74 20.11.2008, 21:53 | ||
По такой причине, может ожидать до ~ 30 сек и срабатывает ошибка, - (опробовано), если конечно разрыва вообще нет будет ждать вечно, ну я думаю это практически не реально, практически всегда сокет разрывается. |
| Автор: J0ker 20.11.2008, 22:03 |
| еще раз ваша функция вернула -1 что это означает? что пользователю-то сказать? |
| Автор: MAKCim 20.11.2008, 22:09 | ||
| SVN74, в общем
|
| Автор: SVN74 20.11.2008, 22:10 | ||
Это означает - ошибка приема данных, если все в порядке вернет количество полученных байт. |
| Автор: MAKCim 20.11.2008, 22:12 |
все ясно литературу мы не читаем |
| Автор: SVN74 20.11.2008, 22:13 |
В принципе можно и так, просто все равно ошибку надо определять через WSAGetLastError() |
| Автор: J0ker 20.11.2008, 22:15 | ||
все равно не получится WSAGetLastError не определена в случае успешного завершения операции |
| Автор: SVN74 20.11.2008, 22:20 | ||
Да, а вот почему то автор "Йон Снейдер Эффективное программирование TCP/IP " определил возврат именно так ... rc = recv( s1, buf, 1, 0 ); 40 if ( rc <= 0 ) 41 { 42 perror( "ошибка вызова recv" ); 43 exit ( 1 ); 44 } |
| Автор: MAKCim 20.11.2008, 22:24 | ||
значит он тоже литературу не читает |
| Автор: SVN74 20.11.2008, 22:29 |
| Хотя я раньше писал if ( rc < 0 ) ... А теперь так... rc = recv( s1, buf, 1, 0 ); 40 if ( rc <= 0 ) |
| Автор: J0ker 20.11.2008, 23:22 | ||
в утиль значит снейдера |
| Автор: vinick 21.11.2008, 00:29 | ||||
Ну в водной главе, в примере простейшего tcp-клиента глупо было бы писать полноценную обработку ошибок ;) А вот дальше... стр 68, листинг 2.12 "Функция readn"
Не надо тут на Снейдера поклеп возводить, он хорошую книжку написал. |
| Автор: SVN74 21.11.2008, 00:38 | ||
Согласен, книга хорошая.
--- Это 58 страница --- |
| Автор: jonie 21.11.2008, 00:43 |
| SVN74 знать надо дочитывать книжки-то дальше введения... |
| Автор: vinick 21.11.2008, 01:56 | ||||
Русские умирают, но не сдаются Читаем двумя строками выше.
Это не пример правильного кода, это заглушка для тестирования каркаса tcpclient.skel. SVN74, прекрати оправдываться. Будь смелым признать ошибку. Ты в чужом топике, в ответ на вопрос человека начинающего работать с сокетами, публикуешь код и утверждаешь что он супер надежный и эффективный. Когда тебе указывают на то, что код содержит ошибки, ты публикуешь другой вариант, уже лучше, но все равно имеющий недочеты. А потом начинаешь дергать "неправильные" цитаты из книги и прикрываться авторитетом автора. Тем самым ты вводишь в заблуждение людей мало знакомых с работой сокетов. ЗЫЖ Да, я зануда |
| Автор: J0ker 21.11.2008, 03:47 |
не нервничайте - для нас нет авторитетов ну хочется человеку мазохизма - зачем ему мешать |
| Автор: Олег2005 24.11.2008, 19:11 | ||
В TCP нет никаких пакетов - и тем более фрагментации Фрагментация осуществляется для IP-v4 только на маршрутизаторах (при определенных условиях - в частности, длина Ip-пакета меньше MTU данной сети) В TCP существует только понятие сегмента. Добавлено @ 19:15 Ошибка вызова функции и ошибка приема данных - это совсем не одно и тоже. Снайдер знал что писал Добавлено через 7 минут и 11 секунд Ну ну, не замахивайтесь на святое |
| Автор: J0ker 29.11.2008, 02:08 |
скажем так TCP сегмент заключен в IP пакет (который в свою очередь заключен в ethernet пакет (обычно)). Возможно разбиение такого пакета на 2 и более - в зависимости от MTU на шлюзах далее в теории никакой фрагментации нет - есть поток но исходя из того, что обработка данных на принимающей стороне выполняется обычно намного быстрее пересылки данных, то фрагментация безусловно ощутима и накладывает определенные условия на функцию приема таким образом, что для новичка очевидное применение recv на самом деле не является правильным. Добавлено @ 02:12 не меньше, а больше не IP, а ethernet (либо другого, канального) (сори ступил) |
| Автор: Олег2005 30.11.2008, 14:47 |
| Согласен - тут я просто перепутал, что больше что меньше. Спасибо за коррекцию.. |